文字列の線形回帰


25

この課題は少し難しいですが、文字列を指定するとかなり簡単sです:

meta.codegolf.stackexchange.com

文字列内の文字の位置をx座標として、ASCII値をy座標として使用します。上記の文字列の場合、結果の座標セットは次のようになります。

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

次に、線形回帰を使用して、収集したセットの勾配とy切片の両方を計算する必要があります。上記のセットをプロットします。

プロット

これにより、(0インデックス付き)の最適な行が得られます。

y = 0.014516129032258x + 99.266129032258

ここだ1インデックスのベストフィットラインは:

y = 0.014516129032258x + 99.251612903226

したがって、プログラムは以下を返します。

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

または(その他の賢明な形式):

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

または(その他の賢明な形式):

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

または(その他の賢明な形式):

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

明らかでない場合は、その形式で返される理由を説明してください。


いくつかの明確化ルール:

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

これは、最低バイト数の勝ちです。


3
勾配とy切片を計算するためのリンク/式はありますか?
ロッド

16
親愛なる不明確な投票者:公式を持っていることは良いことであることに同意しますが、決して必要ではありません。線形回帰は数学の世界では明確に定義されたものであり、OPは方程式の検索を読者に任せたい場合があります。
ネイサンメリル


2
次のような、最適な直線の実際の方程式を返すことはでき0.014516129032258x + 99.266129032258ますか?
グレッグマーティン

2
この課題のタイトルを入れているこの素晴らしい曲をその日の残りのために私の頭の中で
ルイス・Mendoを

回答:


2

MATL、8バイト

n:G3$1ZQ

1ベースの文字列インデックスが使用されます。

オンラインでお試しください!

説明

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

7

オクターブ、29 26 24 20バイト

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

オンラインでお試しください!

モデルがあります

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

これyは文字列のASCII値ですs

パラメーターの切片と勾配を見つけるために、次の方程式を作成できます。

s = [intercept slope] * [1 X]

そう

[intercept slope] = s/[1 x]

!!s文字列を、文字列と同じ長さの1のベクトルに変換します。
1のベクトルは、切片の推定に使用されます。
1:nnz(s)は、1からとして使用される文字列の要素数までの値の範囲ですx

前の答え

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

テストのために、次のコードをOctave Onlineに貼り付けます

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

入力として文字列を受け入れ、モデルの通常の最小二乗推定を適用する関数 y = x*b + e

olsの最初の引数はy、文字列を転置し、s0を追加してASCIIコードを取得することです。


/、 いい案!
ルイスメンドー

6

TI-Basic、51(+ 141)バイト

TI-Basicでは、文字列は1から始まります。

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)

他の例と同様に、これはXに関して最適な直線の方程式を出力します。また、Str2では、TI-Basicで141バイトのこの文字列が必要です。

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

これがプログラムの一部になれない理由は、TI-Basicの2つの文字を文字列に自動的に追加できないためです。1つはSTO->矢印ですが、ASCIIの一部ではないため、これは問題ではありません。もう1つは文字列リテラル(")です。これは、Y=方程式に入力してを使用することによってのみ文字列化できますEqu>String(


私は誰かがこれのために彼らの古い計算機を破壊するだろうかと真剣に思っていました:)。これを考えたとき、古いTI-83を念頭に置いていました。
魔法のタコUr

@carusocomputingおい、いいね!TI-Basicプログラミング言語が大好きで、多くのコードゴルフで使用しています。ASCIIのみがサポートされていれば
...-ティムテック

2つのコメント:1、"プログラムのユーザー入力としても入力することで文字列化できますが、ここでは役に立ちませんが、その事実を指摘したいだけです。2、これらの文字の一部が電卓に存在することを認識していません。私は間違っているかもしれないが、たとえば、どこで入手できますか@~?同様に#$&
パトリックロバーツ

@PatrickRobertsのコメントをありがとう。これらは、0xBBで始まる2バイトのトークンです。tibasicdev.wikidot.com/miscellaneous-tokensの
ティムテック

6

R、46 45バイト

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

stdinから入力を読み取り、指定されたテストケースのリターン(1インデックス):

(Intercept)           x 
99.25161290  0.01451613 

少し短くなりました(ただし、テストされていないため、式の解析で評価の問題が発生する可能性があります):lm(utf8ToInt(y<-scan(,""))~1:nchar(y))$co
rturnbull

@rturnbull最初はこれを試しましたが、x変数を機能させるには事前に定義するlm必要があるようです。
ビリーウォブ

@rturnbull私は可変長が異なるエラーを取得します。与えられているsので、x=1:nchar(s);lm(charToRaw(s)~x)$coいくつかのバイトを節約できます。また$co、インターセプト+係数が得られないため、技術的に必要かどうかもわかりません。
クリス

@クリスそれは実行可能な答えではないことをかなり確信しています。stdinからの入力または関数の引数としての入力が必要です。
ビリーウォブ

フェアは十分、質問のちょうど私の読書-それは同様のpython +オクターブの答えに、より公平な比較を与える
クリス・

5

Python、82 80バイト

@Megoのおかげで-2バイト

を使用してscipy

import scipy
lambda s:scipy.stats.linregress(range(len(s)),list(map(ord,s)))[:2]

名前のないラムダが許可されているので、ドロップできますf=
メゴ

@DigitalTraumaはnumpy.linalg.lstsq明らかに引数が異なり、scipy.stats.linregressより複雑です。
-dfernan

4

Mathematica、31バイト

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

入力として文字列を取り、問題の最適な行の実際の方程式を返す名前のない関数。たとえば、をf=Fit[ToCharacterCode@#,{1,x},x]&; f["meta.codegolf.stackexchange.com"]返します99.2516 + 0.0145161 x

ToCharacterCodeASCII文字列を対応するASCII値のリストに変換します。実際、デフォルトはより一般的にUTF-8です。(このコンテキストでは、1つの関数名がコード長の48%以上を占めるというのは悲しいことです...)そしてFit[...,{1,x},x]、線形回帰を計算するための組み込み関数です。


1
1のインデックスが付いた行の例に感謝します。あなたのおかげで、計算する必要はありませんでした。
魔法のタコUr

4

Node.js、84バイト

を使用してregression

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

デモ

// 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>


3

セージ、76バイト

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

ゴルフをすることはほとんどなく、おそらくゴルフをしたPythonの回答よりも長いかもしれませんが、ええ...


2

J、11バイト

3&u:%.1,.#\

これは、1ベースのインデックス作成を使用します。

オンラインでお試しください!

説明

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

2

JavaScript、151 148バイト

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

より読みやすい:


あなたは削除することで、バイトを保存することができます0からc.charCodeAt(0)移動することで、別の2バイトk=...コンマグループをなどを返される配列の最初のインデックスに直接それを置く[k=...,(d-k*b)/a]
パトリック・ロバーツ

2

Javascript(ES6)、112バイト

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>


2

Haskell、154 142バイト

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

インポートと長い関数名のために、私の好みには長すぎますが、それでもです。私はゴルフの輸入の分野の専門家ではありませんが、他のゴルフの方法は考えられませんでした。

nimiのおかげordで、置換とData.CharfromEnum のインポートにより12バイトを削除しました。


1
あなたは置き換えることができますordfromEnumして取り除きますimport Data.Char
-nimi

1

SASマクロ言語、180バイト

1ベースのインデックスを使用します。出力がスロープとインターセプトのみの場合、ソリューションはかなり冗長になります。

%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;

1

Clojure、160バイト

組み込みなし。パーセプトロンの記事で説明されている反復アルゴリズムを使用します。他の入力に収束しない場合2e-4があります1e5。その場合、学習率を下げて、繰り返し回数を増やします。非反復アルゴリズムを実装する方が短いかどうかはわかりません。

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

例:

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

[99.26612903225386 0.014516129032464659]

1

メープル、65バイト

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

使用法:

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

戻り値:

99.2516129032259+0.0145161290322573*x

注:これは、Fitコマンドを使用して、a * x + bの形式の多項式をデータに近似します。文字列のASCII値は、ingをバイトに変換することで見つかります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.