Regresja liniowa na sznurku

25

To wyzwanie jest trochę trudne, ale raczej proste, biorąc pod uwagę ciąg znaków s:

meta.codegolf.stackexchange.com

Użyj pozycji znaku w łańcuchu jako xwspółrzędnej i wartości ascii jako ywspółrzędnej. W przypadku powyższego ciągu wynikowy zestaw współrzędnych wyglądałby następująco:

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

Następnie musisz obliczyć zarówno nachylenie, jak i punkt przecięcia y zestawu, który uzyskałeś za pomocą regresji liniowej , oto zestaw przedstawiony powyżej:

Wątek

Co daje linię najlepszego dopasowania (indeksowaną 0):

y = 0.014516129032258x + 99.266129032258

Oto linia najlepiej dopasowanych 1-indeksowanych :

y = 0.014516129032258x + 99.251612903226

Twój program zwróci:

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

Lub (dowolny inny rozsądny format):

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

Lub (dowolny inny rozsądny format):

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

Lub (dowolny inny rozsądny format):

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

Po prostu wyjaśnij, dlaczego powraca w tym formacie, jeśli nie jest to oczywiste.


Niektóre zasady wyjaśniające:

- 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).

Jest to wygrana z najmniejszą liczbą bajtów w .

Urna Magicznej Ośmiornicy
źródło
3
Czy masz link / formułę do obliczenia nachylenia i przecięcia y?
Rod
16
Drodzy Niejasni wyborcy: Chociaż zgadzam się, że miło jest mieć formułę, w żadnym wypadku nie jest to konieczne. Regresja liniowa jest dobrze zdefiniowaną rzeczą w świecie matematycznym, a OP może pozostawić znalezienie równania czytelnikowi.
Nathan Merrill
2
Czy dobrze jest zwrócić rzeczywiste równanie linii najlepiej dopasowanej, na przykład 0.014516129032258x + 99.266129032258?
Greg Martin
2
Tytuł tego wyzwania sprawił, że przez resztę dnia w mojej głowie pojawiła się ta cudowna piosenka
Luis Mendo

Odpowiedzi:

2

MATL , 8 bajtów

n:G3$1ZQ

Stosowane jest indeksowanie ciągów 1.

Wypróbuj online!

Wyjaśnienie

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
źródło
7

Oktawa, 29 26 24 20 bajtów

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

Wypróbuj online!

Mamy model

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

Oto ywartość ciągu ASCIIs

Aby znaleźć parametry przechwytywania i nachylenia, możemy utworzyć następujące równanie:

s = [intercept slope] * [1 X]

więc

[intercept slope] = s/[1 x]

!!skonwertuje ciąg na wektor o takiej samej długości jak ciąg.
Wektor jedynek służy do oszacowania przecięcia.
1:nnz(s)to zakres wartości od 1 do liczby elementów ciągu używanego jakox .

Poprzednia odpowiedź

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

Do testu wklej następujący kod do Octave Online

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

Funkcja, która przyjmuje ciąg jako dane wejściowe i stosuje zwykłe oszacowanie modelu metodą najmniejszych kwadratów y = x*b + e

Pierwszym argumentem ols jest yto, że transponujemy ciąg si dodajemy z liczbą 0, aby uzyskać jego kod ASCII.

rahnema1
źródło
/, świetny pomysł!
Luis Mendo,
6

TI-Basic, 51 (+ 141) bajtów

Ciągi są oparte na 1 w 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)

Podobnie jak w innym przykładzie, to wyprowadza równanie linii najlepszego dopasowania pod względem X. Ponadto w Str2 musisz mieć ten ciąg, który w TI-Basic ma 141 bajtów:

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

Powodem, dla którego nie może być częścią programu, jest to, że dwa znaki w TI-Basic nie mogą być automatycznie dodawane do łańcucha. Jedna to STO->strzałka, ale to nie jest problem, ponieważ nie jest częścią ASCII. Drugim jest łańcuch literał ( "), który można skreślić tylko przez wpisanie do Y=równania i użycie Equ>String(.

Timtech
źródło
Zastanawiałem się poważnie, czy ktokolwiek wybiłby do tego swoje stare kalkulatory :). Kiedy to wymyśliłem, miałem na myśli mój stary TI-83.
Magic Octopus Urn
@carusocomputing Cześć, miło! Bardzo podoba mi się język programowania TI-Basic i używam go do wielu moich golfowych kodów. Gdyby tylko wspierał ASCII ...
Timtech
Dwa komentarze: 1, możesz skreślić, prosząc "go o wpisanie również przez użytkownika w programie, co nie pomaga ci tutaj, ale chciałem tylko podkreślić ten fakt. 2, nie rozpoznaję niektórych z tych znaków jako istniejących na kalkulatorze. Mogę się mylić, ale na przykład, skąd można dostać @i ~? Jak również #, $i &.
Patrick Roberts,
Dzięki za komentarz, @PatrickRoberts. Są to dwubajtowe tokeny zaczynające się od 0xBB. Spójrz w kolumnie D tibasicdev.wikidot.com/miscellaneous-tokens
Timtech
6

R, 46 45 bajtów

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

Odczytuje dane wejściowe ze standardowego wejścia i dla podanych przypadków testowych zwraca (indeksowane jednym):

(Intercept)           x 
99.25161290  0.01451613 
Billywob
źródło
Nieco krótszy (ale nieprzetestowany, być może pewne problemy z oceną podczas analizowania formuły):lm(utf8ToInt(y<-scan(,""))~1:nchar(y))$co
rturnbull
@rturnbull Na początku próbowałem, ale wydaje się, że xzmienna musi być wstępnie zdefiniowana, lmaby działała.
Billywob,
@rturnbull Dostaję zmienne długości różnią się od tego błędem. Dano nam, swięc x=1:nchar(s);lm(charToRaw(s)~x)$cooszczędza niektóre bajty. Nie wiem też, czy $cojest to technicznie konieczne, ponieważ nadal otrzymujesz współczynnik przechwytywania + bez niego
Chris
@Chris Dość pewna, że ​​to nie jest realna odpowiedź. Powinny być jakieś dane wejściowe ze stdin lub jako argument funkcji.
Billywob,
W porządku, po prostu moje czytanie pytania - daje to bardziej uczciwe porównanie z python + odpowiedzi oktawowe
Chris
5

Python, 82 80 bajtów

-2 bajty dzięki @Mego

Używanie scipy:

import scipy
lambda s:scipy.stats.linregress(range(len(s)),list(map(ord,s)))[:2]
dfernan
źródło
Nienazwane lambdy są dozwolone, więc możesz upuścić f=.
Mego
@DigitalTrauma numpy.linalg.lstsqnajwyraźniej różni się argumentami scipy.stats.linregressi jest bardziej złożony.
dfernan
4

Mathematica, 31 bajtów

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

Nienazwana funkcja pobierająca ciąg wejściowy i zwracająca faktyczne równanie najlepiej pasującej linii. Na przykład f=Fit[ToCharacterCode@#,{1,x},x]&; f["meta.codegolf.stackexchange.com"]zwraca 99.2516 + 0.0145161 x.

ToCharacterCodekonwertuje ciąg ASCII na listę odpowiednich wartości ASCII; w rzeczywistości domyślnie jest to UTF-8 bardziej ogólnie. (Trochę smutne, w tym kontekście, że nazwa jednej funkcji stanowi ponad 48% długości kodu ....) I Fit[...,{1,x},x]jest wbudowana do obliczania regresji liniowej.

Greg Martin
źródło
1
Dzięki za przykład linii 1-indeksowanej, nie musiałem jej obliczać z powodu ciebie haha.
Magic Octopus Urn
4

Node.js, 84 bajtów

Używanie regression:

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

Próbny

// 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
źródło
3

Szałwia, 76 bajtów

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

Prawie żadna gra w golfa, prawdopodobnie dłuższa niż golfowa odpowiedź Pythona, ale tak ...

busukxuan
źródło
2

J , 11 bajtów

3&u:%.1,.#\

Korzysta z indeksowania w oparciu o jeden.

Wypróbuj online!

Wyjaśnienie

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
mile
źródło
2

JavaScript, 151 148 bajtów

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])

Bardziej czytelny:

Markus Jarderot
źródło
Można zapisać bajt poprzez usunięcie 0z c.charCodeAt(0), a kolejne 2 bajty przez przeniesienie k=...grupy przecinek i umieszczenie go bezpośrednio w pierwszym indeksem od zwróconej tablicy jak[k=...,(d-k*b)/a]
Patrick Roberts
2

JavaScript (ES6), 112 bajtów

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
źródło
2

Haskell, 154 142 bajty

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

Jest o wiele za długi dla moich upodobań ze względu na import i długie nazwy funkcji, ale cóż. Nie mogłem wymyślić żadnej innej metody gry w golfa, chociaż nie jestem ekspertem w dziedzinie importu golfa.

Usunięto 12 bajtów, zastępując je ordi importując Data.Charprzez fromEnum dzięki nim.

Renzeee
źródło
1
Można wymienić ordz fromEnumi pozbyć import Data.Char.
nimi
1

SAS Macro Language, 180 bajtów

Wykorzystuje indeksowanie 1. Rozwiązanie staje się dość niewygodne, gdy wyjście jest tylko nachyleniem i przechwyceniem.

%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
źródło
1

Clojure, 160 bajtów

Brak wbudowanych, wykorzystuje iteracyjny algorytm opisany w artykule Perceptron . Może nie zbiegać się z innymi danymi wejściowymi, w takim przypadku obniż szybkość uczenia się 2e-4i może zwiększyć liczbę iteracji 1e5. Nie jestem pewien, czy nie iteracyjny algorytm byłby krótszy do wdrożenia.

#(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)

Przykład:

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

[99.26612903225386 0.014516129032464659]
NikoNyrh
źródło
1

Klon, 65 bajtów

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

Stosowanie:

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

Zwroty:

99.2516129032259+0.0145161290322573*x

Uwagi: Używa polecenia Dopasuj, aby dopasować wielomian formy a * x + b do danych. Wartości ASCII dla ciągu można znaleźć, konwertując na bajty.

DSkoog
źródło