Regresi Linier pada String

25

Tantangan ini sedikit rumit, tetapi agak sederhana, diberi string s:

meta.codegolf.stackexchange.com

Gunakan posisi karakter dalam string sebagai xkoordinat dan nilai ascii sebagai ykoordinat. Untuk string di atas, set koordinat yang dihasilkan adalah:

0, 109
1, 101
2, 116
3, 97
4, 46
5, 99
6, 111
7, 100
8, 101
9, 103
10,111
11,108
12,102
13,46
14,115
15,116
16,97
17,99
18,107
19,101
20,120
21,99
22,104
23,97
24,110
25,103
26,101
27,46
28,99
29,111
30,109

Selanjutnya, Anda harus menghitung kemiringan dan intersepsi y dari set yang telah Anda kumpulkan menggunakan Regresi Linier , inilah set di atas yang diplot:

Merencanakan

Yang menghasilkan garis paling pas (0-diindeks):

y = 0.014516129032258x + 99.266129032258

Inilah baris paling cocok yang diindeks 1 :

y = 0.014516129032258x + 99.251612903226

Jadi program Anda akan kembali:

f("meta.codegolf.stackexchange.com") = [0.014516129032258, 99.266129032258]

Atau (Format masuk akal lainnya):

f("meta.codegolf.stackexchange.com") = "0.014516129032258x + 99.266129032258"

Atau (Format masuk akal lainnya):

f("meta.codegolf.stackexchange.com") = "0.014516129032258\n99.266129032258"

Atau (Format masuk akal lainnya):

f("meta.codegolf.stackexchange.com") = "0.014516129032258 99.266129032258"

Cukup jelaskan mengapa itu kembali dalam format itu jika tidak jelas.


Beberapa aturan klarifikasi:

- Strings are 0-indexed or 1 indexed both are acceptable.
- Output may be on new lines, as a tuple, as an array or any other format.
- Precision of the output is arbitrary but should be enough to verify validity (min 5).

Ini adalah kemenangan byte-count terendah.

Guci Gurita Ajaib
sumber
3
Apakah Anda memiliki tautan / rumus untuk menghitung kemiringan dan intersepsi y?
Rod
16
Para pemilih yang tidak jelas: Walaupun saya setuju bahwa itu baik untuk memiliki formula, itu sama sekali tidak perlu. Regresi linier adalah hal yang terdefinisi dengan baik di dunia matematika, dan OP mungkin ingin menyerahkan persamaannya kepada pembaca.
Nathan Merrill
2
Apakah saya tetap bisa mengembalikan persamaan aktual dari garis paling cocok, seperti 0.014516129032258x + 99.266129032258?
Greg Martin
2
Judul tantangan ini telah menempatkan lagu yang luar biasa ini di kepalaku selama sisa hari itu
Luis Mendo

Jawaban:

2

MATL , 8 byte

n:G3$1ZQ

Pengindeksan string berbasis 1 digunakan.

Cobalah online!

Penjelasan

n:     % Input string implicitly. Push [1 2 ... n] where n is string length.
       % These are the x values
G      % Push the input string. A string is an array of chars, which is
       % equivalent to an array of ASCII codes. These are the y values
3$     % The next function will use 3 inputs
1      % Push 1
ZQ     % Fit polynomial of degree 1 to those x, y data. The result is an
       % array with the polynomial coefficients. Implicitly display
Luis Mendo
sumber
7

Oktaf, 29 26 24 20 byte

@(s)s/[!!s;1:nnz(s)]

Cobalah secara Online!

Kami punya modelnya

y= intercept *x^0 + slope * x
 = intercept * 1  + slope * x

Berikut yadalah nilai string ASCIIs

Untuk menemukan parameter intersep dan slope kita dapat membentuk persamaan berikut:

s = [intercept slope] * [1 X]

begitu

[intercept slope] = s/[1 x]

!!smengkonversi string ke vektor yang panjangnya sama dengan string.
Vektor yang digunakan untuk estimasi intersep.
1:nnz(s)adalah rentang nilai dari 1 hingga jumlah elemen string yang digunakan sebagai x.

Jawaban sebelumnya

@(s)ols(s'+0,[!!s;1:nnz(s)]')

Untuk uji tempel kode berikut ke Octave Online

(@(s)ols(s'+0,[!!s;1:nnz(s)]'))('meta.codegolf.stackexchange.com')

Fungsi yang menerima string sebagai input dan menerapkan estimasi model kuadrat terkecil biasa y = x*b + e

Argumen pertama ols adalah yuntuk itu kita memindahkan string sdan menambahkan dengan angka 0 untuk mendapatkan kode ASCII-nya.

rahnema1
sumber
/, ide yang hebat!
Luis Mendo
6

TI-Basic, 51 (+ 141) byte

String 1-based di TI-Basic.

Input Str1
seq(I,I,1,length(Str1->L1
32+seq(inString(Str2,sub(Str1,I,1)),I,1,length(Str1->L2
LinReg(ax+b)

Seperti contoh lainnya, ini menghasilkan persamaan garis paling cocok, dalam hal X. Juga, di Str2 Anda harus memiliki string ini, yaitu 141 byte di TI-Basic:

! "# $% & '() * +, -. / 0123456789:; <=>? @ ABCDEFGHIJKLMNOPQRSTUVWXYZ [] ^ _abcdefghijklmnopqrstuvwxyz{|}~

Alasan ini tidak dapat menjadi bagian dari program ini adalah karena dua karakter dalam TI-Basic tidak dapat secara otomatis ditambahkan ke string. Satu adalah STO->panah, tetapi ini bukan masalah karena itu bukan bagian dari ASCII. Yang lainnya adalah string literal ( "), yang hanya dapat diketikkan dengan mengetikkan ke dalam Y=persamaan dan menggunakan Equ>String(.

Timtech
sumber
Saya benar-benar bertanya-tanya apakah ada yang mau menghancurkan kalkulator lama mereka untuk ini :). Saya memikirkan TI-83 lama saya ketika saya memikirkan hal ini.
Magic Gurita Guci
@carusocomputing Hei, bagus! Saya sangat menyukai bahasa pemrograman TI-Basic dan saya menggunakannya untuk banyak kode golf saya. Andai saja ia mendukung ASCII ...
Timtech
Dua komentar: 1, Anda dapat merangkai "dengan meminta sebagai input pengguna dalam sebuah program juga, yang tidak membantu Anda di sini, tapi saya hanya ingin menunjukkan fakta itu. 2, saya tidak mengenali beberapa karakter yang ada di kalkulator. Saya bisa saja salah, tetapi misalnya, di mana Anda mendapatkan @dan ~? Serta #, $, dan &.
Patrick Roberts
Terima kasih atas komentarnya, @ Patrickrickobert. Itu adalah token dua byte yang dimulai dengan 0xBB. Lihat di Kolom D dari tibasicdev.wikidot.com/miscellaneous-tokens
Timtech
6

R, 46 45 byte

x=1:nchar(y<-scan(,""));lm(utf8ToInt(y)~x)$co

Membaca input dari stdin dan untuk pengembalian test case yang diberikan (satu-diindeks):

(Intercept)           x 
99.25161290  0.01451613 
Billywob
sumber
Sedikit lebih pendek (tetapi belum teruji, mungkin beberapa masalah evaluasi dalam menguraikan formula):lm(utf8ToInt(y<-scan(,""))~1:nchar(y))$co
rturnbull
@rturnbull Saya mencoba ini pada awalnya tetapi sepertinya xvariabel harus ditentukan sebelumnya lmagar berfungsi.
Billywob
@rturnbull Saya mendapatkan kesalahan panjang variabel yang berbeda pada itu. Kami diberi sbegitu x=1:nchar(s);lm(charToRaw(s)~x)$comenghemat beberapa byte. Saya juga tidak tahu apakah $cosecara teknis diperlukan, karena Anda masih mendapatkan koefisien intersep + tanpanya
Chris
@ Chris Cukup yakin itu bukan jawaban yang layak. Harus ada beberapa masukan dari stdin atau sebagai argumen fungsi.
Billywob
Cukup adil, hanya membaca pertanyaan saya - itu memberikan perbandingan yang lebih adil untuk python + oktaf jawaban juga
Chris
5

Python, 82 80 byte

-2 byte terima kasih kepada @Mego

Menggunakan scipy:

import scipy
lambda s:scipy.stats.linregress(range(len(s)),list(map(ord,s)))[:2]
dfernan
sumber
Lambda yang tidak disebutkan namanya diizinkan, sehingga Anda dapat membatalkannya f=.
Mego
@DigitalTrauma numpy.linalg.lstsqrupanya berbeda dalam argumen scipy.stats.linregressdan lebih kompleks.
dfernan
4

Mathematica, 31 byte

Fit[ToCharacterCode@#,{1,x},x]&

Fungsi tanpa nama mengambil string sebagai input dan mengembalikan persamaan aktual dari garis paling pas yang dimaksud. Misalnya, f=Fit[ToCharacterCode@#,{1,x},x]&; f["meta.codegolf.stackexchange.com"]kembali 99.2516 + 0.0145161 x.

ToCharacterCodemengonversi string ASCII ke daftar nilai ASCII yang sesuai; memang, secara default ke UTF-8 lebih umum. (Agak menyedihkan, dalam konteks ini, bahwa satu nama fungsi terdiri lebih dari 48% dari panjang kode ....) Dan Fit[...,{1,x},x]merupakan bawaan untuk menghitung regresi linier.

Greg Martin
sumber
1
Terima kasih untuk contoh baris 1-diindeks, tidak harus menghitungnya karena Anda haha.
Magic Gurita Guci
4

Node.js, 84 byte

Menggunakan regression:

s=>require('regression')('linear',s.split``.map((c,i)=>[i,c.charCodeAt()])).equation

Demo

// polyfill, since this is clearly not Node.js
function require(module) {
  return window[module];
}
// test
["meta.codegolf.stackexchange.com"].forEach(function test(string) {
  console.log(string);
  console.log(this(string));
},
// submission
s=>require('regression')('linear',s.split``.map((c,i)=>[i,c.charCodeAt()])).equation
);
<script src="https://cdn.rawgit.com/Tom-Alexander/regression-js/master/src/regression.js"></script>

Patrick Roberts
sumber
3

Sage, 76 byte

var('m','c')
y(x)=m*x+c
f=lambda x:find_fit(zip(range(len(x)),map(ord,x)),y)

Hampir tidak ada golf, mungkin lebih lama dari jawaban Python golf, tapi ya ...

busukxuan
sumber
2

J , 11 byte

3&u:%.1,.#\

Ini menggunakan pengindeksan berbasis satu.

Cobalah online!

Penjelasan

3&u:%.1,.#\  Input: string S
         #\  Get the length of each prefix of S
             Forms the range [1, 2, ..., len(S)]
      1,.    Pair each with 1
3&u:         Get the ASCII value of each char in S
    %.       Matrix divide
mil
sumber
2

JavaScript, 151 148 byte

s=>([a,b,c,d,e]=[].map.call(s,c=>c.charCodeAt()).reduce(([a,b,c,d,e],y,x)=>[a+1,b+x,c+x*x,d+y,e+x*y],[0,0,0,0,0]),[k=(e*a-b*d)/(c*a-b*b),(d-k*b)/a])

Lebih mudah dibaca:

Markus Jarderot
sumber
Anda dapat menyimpan byte dengan menghapus 0dari c.charCodeAt(0), dan 2 byte lainnya dengan memindahkan k=...grup koma dan meletakkannya langsung di indeks pertama dari array yang dikembalikan seperti[k=...,(d-k*b)/a]
Patrick Roberts
2

Javascript (ES6), 112 byte

s=>[m=(a=b=c=d=0,([...s].map((u,x)=>{a+=n=x,b+=y=u.charCodeAt(),c+=x*x,d+=x*y}),++n)*d-a*b)/(n*c-a*a),b/n-m*a/n]

F=s=>[m=(a=b=c=d=0,([...s].map((u,x)=>{a+=n=x,b+=y=u.charCodeAt(),c+=x*x,d+=x*y}),++n)*d-a*b)/(n*c-a*a),b/n-m*a/n]

const update = () => {
  console.clear();
  console.log(F(input.value));
};
input.oninput = update;
update();
#input {
  width: 100%;
  box-sizing: border-box;
}
<input id="input" type="text" value="meta.codegolf.stackexchange.com" length=99/>
<div id="output"></div>

George Reith
sumber
2

Haskell, 154 142 byte

import Statistics.LinearRegression
import Data.Vector
g x=linearRegression(generate(Prelude.length x)i)$i.fromEnum<$>fromList x
i=fromIntegral

Terlalu panjang untuk kesukaan saya karena impor dan nama fungsi yang panjang, tapi yah. Saya tidak bisa memikirkan metode Golf lain yang tersisa, meskipun saya tidak ahli dalam bidang impor golf.

Melucuti 12 byte dengan mengganti orddan impor Data.Charoleh fromEnum berkat nimi.

Renzeee
sumber
1
Anda dapat mengganti orddengan fromEnumdan menyingkirkannya import Data.Char.
nimi
1

SAS Macro Language, 180 byte

Menggunakan pengindeksan berbasis 1. Solusinya menjadi sangat bertele-tele ketika output hanya kemiringan dan mencegat.

%macro t(a);data w;%do i=1 %to %length(&a);x=&i;y=%sysfunc(rank(%substr(&a,&i,1)));output;%end;run;proc reg outtest=m;model y=x/noprint;run;proc print data=m;var x intercept;%mend;
J_Lard
sumber
1

Clojure, 160 byte

Tidak ada built-in, menggunakan algoritma iteratif yang dijelaskan pada artikel Perceptron . Mungkin tidak menyatu pada input lain, dalam hal ini menurunkan tingkat pembelajaran 2e-4dan mungkin meningkatkan jumlah iterasi 1e5. Tidak yakin apakah algoritma non-iteratif akan lebih pendek untuk diterapkan.

#(nth(iterate(fn[p](let[A apply e(for[x(range(count %))](-(int(get % x))(*(p 1)x)(p 0)))](mapv(fn[p e](+(* e 2e-4)p))p[(A + e)(A +(map *(range)e))])))[0 0])1e5)

Contoh:

(def f #( ... ))
(f "meta.codegolf.stackexchange.com")

[99.26612903225386 0.014516129032464659]
NikoNyrh
sumber
1

Maple, 65 byte

Statistics:-LinearFit(b*x+a,[$(1..length(s))],convert(s,bytes),x)

Pemakaian:

s := "meta.codegolf.stackexchange.com";
Statistics:-LinearFit(b*x+a,[$(1..length(s))],convert(s,bytes),x);

Pengembalian:

99.2516129032259+0.0145161290322573*x

Catatan: Ini menggunakan perintah Fit untuk menyesuaikan polinomial dari bentuk a * x + b ke data. Nilai ASCII untuk string ditemukan dengan mengonversikan ke byte.

DSkoog
sumber