字符串上的线性回归


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
挑战赛的标题已经让这首美妙的歌曲在我余下的一天
Luis Mendo

Answers:


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: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为此我们转置字符串s并添加数字0以获取其ASCII码。


/, 好点子!
路易斯·门多

6

TI基本(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中的两个字符无法自动添加到字符串中。一个是STO->箭头,但这不是问题,因为它不是ASCII的一部分。另一个是字符串文字("),只能通过键入Y=公式并使用来进行字符串化Equ>String(


我很想知道是否有人会为此淘汰旧的计算器:)。想到这一点时,我就想到了旧的TI-83。
Magic Octopus Urn'1

@carusocomputing嘿,太好了!我非常喜欢TI-Basic编程语言,并且在很多代码开发中都使用它。如果仅支持ASCII ...
Timtech '17

有两条评论:1,您也可以"通过在程序中作为用户输入来提示输入来进行字符串化,这对您没有帮助,但我只是想指出这一点。2,我不认识计算器中存在的某些字符。我可能是错的,但是,例如,你在哪里得到@~?还有#$&
Patrick Roberts

感谢您的评论,@ PatrickRoberts。这些是以0xBB开头的两字节令牌。查看tibasicdev.wikidot.com/miscellaneous-tokens的
Timtech,

6

R,46 45字节

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

从stdin读取输入,并为给定的测试用例返回(一个索引):

(Intercept)           x 
99.25161290  0.01451613 

稍短(但未经测试,可能在解析公式时会出现一些评估问题):lm(utf8ToInt(y<-scan(,""))~1:nchar(y))$co
rturnbull

@rturnbull我最初尝试过此方法,但似乎x必须预先定义该变量lm才能正常工作。
Billywob

@rturnbull我得到一个可变的长度不同的错误。我们给出s这样x=1:nchar(s);lm(charToRaw(s)~x)$co可以节省一些字节。我也不知道这$co在技​​术上是否必要,因为如果没有它,您仍然会得到截距+系数
克里斯(Chris

@克里斯绝对确定这不是一个可行的答案。应该有来自stdin或作为函数参数的输入。
Billywob

足够公平,只是我对问题的阅读-它也与python +八度音阶答案进行了更公平的比较
克里斯(Chris

5

Python,82 80字节

-2个字节,感谢@Mego

使用scipy

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

允许使用未命名的Lambda,因此您可以删除f=
Mego

@DigitalTrauma numpy.linalg.lstsq显然在论点上有所不同,scipy.stats.linregress并且更为复杂。
dfernan'1

4

Mathematica,31个字节

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

未命名函数,将字符串作为输入并返回所讨论的最佳拟合线的实际方程式。例如,f=Fit[ToCharacterCode@#,{1,x},x]&; f["meta.codegolf.stackexchange.com"]return 99.2516 + 0.0145161 x

ToCharacterCode将ASCII字符串转换为相应ASCII值的列表;实际上,它更普遍地默认为UTF-8。(在这种情况下,Kinda感到遗憾,一个函数名称占代码长度的48%以上。Fit[...,{1,x},x]


1
感谢您使用1索引行的示例,因为您哈哈,所以不必进行计算。
Magic Octopus Urn'1

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,.#\

这使用基于一个的索引。

在线尝试!

说明

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),并通过移动k=...逗号组并将其直接放在返回数组的第一个索引中来另外保存2个字节,例如[k=...,(d-k*b)/a]
Patrick Roberts

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,154142字节

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

由于导入和长函数名,对于我来说,它太长了,但是很好。尽管我不是高尔夫进口领域的专家,但我想不出其他任何高尔夫方法。

多亏了nimi,通过替换ordData.Charby byEnum 的导入剥离了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字节

没有内置功能,使用Perceptron article上描述的迭代算法。可能不会收敛于其他输入,在这种情况下,降低学习率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

Maple,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

注意:这使用“ 拟合”命令将形式为a * x + b的多项式拟合到数据中。通过转换为字节可以找到字符串的ASCII值。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.