杠杆模拟器2015


46

为什么是模拟器?

这些天,孩子们没有时间也没有野心去实际堆放跷跷板上的盒子或玩耍平衡物体。根据我的模型,这为软件杠杆市场留出了很大的空间,根据我的模型,这将疯狂地出售!

想要编程帮助

我已经为此类游戏申请了专利(正在申请中),但需要专业的程序员来为我编写游戏逻辑。根据我的理解,根据最终程序的字节大小补偿程序员是一种标准做法。因此,我将把这份有利可图的合同授予出价最低的人。

规格

杠杆是一系列由支点平衡的盒子或空白区域。每个盒子的重量从19,空格没有重量。如您所知,盒子在杠杆上的重量与盒子离支点的距离成正比。一个4位于支点第三空间的重物盒将向12杠杆的那一侧施加有效的力单位。

我需要一个程序,给定一个输入杆,该程序将输出该杆是向左,向右倾斜还是完全平衡。

I / O准则

  • 您将为我编写一个程序。
  • 输入将包含一行文本。
  • 输入将来自stdin或作为一个命令行字符串。
  • 框将由字符“ 1”至“ 9”表示。这些字符代表各自的权重。空的空格将由空格' '表示。支点将以尖号' ^'表示。

样本输入杆可能类似于: 8 2^ 941

该杠杆是完美平衡的: (4*8) + 0 + 0 + (1*2) == 0 + (2*9) + (3*4) + (4*1) == 34

  • 不会有前导或尾随空格。不会有尾随换行符。
  • 无需处理格式错误的输入,输入将始终仅具有一个支点,并且只有数字和空格。
  • 输出将指示杠杆是左重,右重还是平衡。
  • 您的程序必须完全有3个可能由格式正确的输入产生的输出。您可以选择这些。
  • 输出必须打印到程序stdout或作为程序的返回码。

测试用例

这里我用LRB是指左重,权重,平衡:

  1. 输入:11 ^9输出:B

  2. 输入:321^ 12输出:L

  3. 输入:9^ 1输出:R

(如果任何人有一些“更复杂”的测试用例,请随时对其进行编辑)。

参考书目

不必要地受到启发,但与在跷跷板上平衡一组重量有关


8
The output must either be print to stdout or be the return code of the program.好吧,现在您要我分发使用跷跷板符号表示退出代码的Linux发行版。

1
我会去玩跷跷板/跷跷板游戏,除非大多数游乐场都将它们移开,因为它们“不安全”。我希望他们不要因此而取消秋千。“孩子们可能会跳下来,哦,不!”
mbomb007

2
输入的边可以空吗?如^1616^^?(假设可以)
Runium,2015年

啊,规格上有个洞,是的,我想侧面可以是空的
turbulencetoo 2015年

7
我只花了几秒钟长琢磨着怎么11 3的偏移或4都不可能与9偏移来平衡1
詹姆斯·索普

Answers:


7

Python 2,69个字节

lambda s:cmp(sum(ord(c)%16*(i-s.find('^'))for i,c in enumerate(s)),0)

模数ord(c)%16提取数字字符的值,同时获得0的空格。对于每个角色,其扭矩贡献将计算为其重量乘以到枢轴的符号距离i-s.find('^'),然后将这些总和与0进行比较,得出之一-1,0,1^计算出角色的权重为14,但这并不重要,因为它位于枢轴上。

Maltysen制作的一个18字节的Pyth端口

._s.e*-kxz\^%Cb16z

对于Python代码,如果需要完整的程序,则为79个字节。想法是开始将索引i移位s.find('^'),并使其倒数。

s=raw_input()
t=0;i=s.find('^')
for c in s:t-=ord(c)%16*i;i-=1
print cmp(t,0)

这是一个使用您的方法的Pyth程序,如果您需要pyth.herokuapp.com/…18个字节,可以将其发布。我自己发布该消息并不正确。
马蒂森(Maltysen)2015年

@Maltysen谢谢,我把它包括在内。
xnor

16

Javascript ES6,62个字节

s=>Math.sign([...s].reduce((p,c,i)=>p+~~c*(i-s.indexOf`^`),0))
  • -1 如果离开更重
  • 0 如果平衡
  • 1 如果权利更重

取消高尔夫:

s=>
  Math.sign(                     // output sign of weight of lever
    [...s].reduce((p,c,i)=>      // split and reduce input
      p+~~c*(i-s.indexOf`^`),0)) // add weights of all elements
                                 //   (elements left of pivot are negatively weighted)

测试运行(将匿名函数分配给f):

>> f("11   ^9")
<< 0

>> f("321^  12")
<< -1

>> f("9^         1")
<< 1

  • -11个字节:将输出从更改R B L-1 0 1
  • -3个字节:更改e.split``[...e](感谢@Vɪʜᴀɴ)
  • -33字节:将算法更改为使用负权重,而不是在枢轴处拆分
  • -9个字节:删除了数据透视检查(显然,结果~~'^'0...)
  • -2字节:使函数匿名(感谢@cᴏɴᴏʀ-obʀɪᴇɴ)

3
一般共识是您可以省略领导,f=并说它会产生匿名功能。(FYI为2个字节)
Conor O'Brien 2015年

5

Japt,22个字节

JaptJa vaScri pt的缩写。口译员

U¬r@X+~~Y*(Z-Ub'^),0 g

返回-1L0B,和1R

这个怎么运作

Uq r@X+~~Y*(Z-Ub'^),0 g
                         // Implicit: U = input string
Uq r@              ,0    // Reduce the input by this function, starting at 0:
     X+~~Y*              //  Return the previous value, plus the current value times
           (Z-Ub'^)      //   the current index minus the index of "^" in U.
                      g  // Take the sign of the resulting number.
                         // Implicit: output last expression

5

APL,39 30字节

{×+/(10|⍵⍳⍨∊⍕¨⍳9)×(⍳⍴⍵)-⍵⍳'^'}

重新阅读规则后,我将其更改为output -1 0 1而不是L B R,节省了9个字节。

在这里尝试。


4

Pyth,20个字节

._s*V-Rxz\^Uzm.xsd0z

测试套件

-1用于左偏, 0用于平衡, 1用于右偏。

这个怎么运作:

._s*V-Rxz\^Uzm.xsd0z
                        z = input()
                        Weights:
             m     z    Map over z
              .x        try:
                sd           cast charater to int
                  0     except: 0
                        Lever arm:
           Uz           range(len(input()))
     -Rxz\^             Subtract index of caret from each value.
   *V                   Vectorized multiplication.
  s                     Sum.
._                      Take sign and print.

4

Haskell,116 96 82 76字节

 f x=signum$sum$zipWith(*)[-length(fst$span(<'^')x)..]$(`mod`16).fromEnum<$>x

输出0用于平衡,-1用于左重和1用于右重。

用法示例:f "321^ 12"->-1

工作原理:在之前找到零件^。将输入字符串和权重列表相乘,该权重列表以开头- length-of-first-part。的^权重为0,且不加和。我正在使用@xnor的mod 16技巧将数字/空格转换为整数值。如果总和为负(正),则杠杆为左重(右重),如果总和为0,则平衡。


4

TeaScript,23 字节 25

我试图写一个Pyth答案,但是那太可怕了:\

$²xd»l+~~i*(a-xi`^`),0©

²看起来很出位,但它可以节省1个字节,所以我会保持它。

在线尝试!

测试所有情况

对于输出方案,我选择了:

  • -1如果Left重于Right(L
  • 0如果Left与Right(B)一样重
  • 1是左小于右(R

取消&&说明

这将使用地图,并减少工作量。

$C(xd(#l+~~i*(a-xi`^`),0))

              // Implicit: x = input
$C(           // Compare...
  xd(#        // Reduce...
    l+          // Pending weight...
    ~~i         // Current weight -> int times...
    (a-         // Total length minus...
    xi`^`       // Fulcrum location
  ,0)
)             // Implicit: Output result

4

pb349329字节

^w[B!94]{>}w[B!0]{vb[T]^t[T+1]>}vb[46]<w[B!0]{<}b[1]vvb[46]^^t[X]w[X!0]{<b[T-X]}^w[B!0]{w[B=32]{b[48]}>}w[X!0]{<t[B-48]vb[B*T]^}w[B!0]{vt[B]vb[1]>^w[B!46]{>}vvb[B+T]^w[B=0]{<}b[0]^b[0]^>}vb[0]vvt[B]<w[B!0]{<}t[B+T]^>[T]w[X!0]{b[10]<}<[T]w[X!0]{b[16]>}vw[B=0]{>}t[B]b[0]w[B=0]{>}t[T-B]b[0]^<[X-T]t[B]<[X]>w[B!0]{b[0]>}<[X]^b[T+66]

这是一个棘手的问题。pb并非设计为擅长于这种事情。它甚至没有乘法但是,它有效。

埃德 注意:我只是说pb没有乘法吗?什么?pb肯定有乘法。我设计并实现了这种语言,我应该知道它内置了乘法运算,而不必做一些愚蠢的循环加法。解决该问题(以及现在可以进行一些创造性的重新排列(使我几乎可以从几乎完全不同的角度解决问题的那一部分))节省了20个字节。不好意思

最难的部分是在获得每一面的(权重*距离)之和后,实际确定要打印的字母。pb没有>or <运算符,只有==and !=。没有简单的方法来判断哪个值更大。我什至无法减去并与0进行比较...除非我做一些非常愚蠢的事情。

  • 找到两个总和。
  • 在未用于任何东西的线上向右偏远。
  • 直到达到X = 0,向左走并放置'L'。
  • 在X = 0处放置一个“ B”。
  • 向左移两个和之和。
  • 直到X = 0,再右移并放置'R'。

然后,您只需转到X =(左侧-右侧),就可以找到答案!删除该行上的所有内容以进行清理,然后打印在(0,0)处找到的值。

...但是有一种更短的方法。不要使用“ L”,“ B”和“ R”,而是使用这些值-“ B”,并在打印时重新添加“ B”。这样,您不必将“ B”放置在X = 0处,只需将其保留为0即可。唯一的问题是,执行此操作后,程序在监视模式下会变得非常愚蠢。'L'-'B'==76-66==10=='\n'。一切似乎都运行良好,直到突然打印出大量的换行符,并且无法跟踪正在发生的事情:D在pbi的常规执行模式下,一切正常,因为在将任何内容打印到行之前删除了换行符安慰。

^w[B!94]{>}                 # Find the fulcrum

w[B!0]{                     # Starting at the fulcrum and going right:
    vb[T]^                    # Store the T below each character of input
    t[T+1]                    # Increment T
    >
}

vb[46]                      # Put a '.' at the end of the values below the input

<w[B!0]{<}                  # Go to the space below the fulcrum
b[1]                        # Put a 1 (So the fulcrum will be represented as '.' later)
vvb[46]^^                   # Put a 46 two spaces below it

t[X]                        # Store the current X value in T
w[X!0]{<                    # Until reaching the beginning of the input:
    b[T-X]                    # Put T - (the current X value) below each byte
}

^w[B!0]{                    # For each byte of input:
    w[B=32]{b[48]}            # Set spaces to '0'
    >
}

w[X!0]{<                    # For each byte of input:
    t[B-48]                   # Set T to the value of the number (fulcrum becomes '.')
    vb[B*T]^                  # Multiply the value below by T
}

# This has nothing to do with the input, except that it's the right length:
w[B!0]{                     # For every byte of input:
    v                         # Go to the value below it
    t[B]                      # Store it in T
    vb[1]>^                   # Put a flag below it
    w[B!46]{>}                # Go to the next '.' value
    vvb[B+T]                  # Add T to whatever is two spaces below the '.'
                              # This will cause the sum for the right side of
                              # the fulcrum to be 46 too high. This is why 46
                              # was left below the fulcrum earlier: both sums
                              # will be off by the same amount.
    ^w[B=0]{<}                # Go back to the flag
    b[0]^b[0]                 # Erase the flag and the value above it
    ^>
}

vb[0]                       # Erase the stray '.'
vvt[B]<w[B!0]{<}t[B+T]      # Get the sum of the two sums
^>[T]                       # Go right that far
w[X!0]{b[10]<}              # Head back to X=0, leaving 'L'-'B' the whole way
<[T]                        # Go left the same amount as before
w[X!0]{b[16]>}              # Head back to X=0, leaving 'R'-'B' the whole way
vw[B=0]{>}                  # Find the sum from left of the fulcrum
t[B]b[0]                    # Save it to T and erase it from the canvas
w[B=0]{>}                   # Find the other sum
t[T-B]b[0]                  # Subtract it from T and erase it from the canvas
^<[X-T]                     # On the line that was just prepared, go to X=T
t[B]                        # Save the value of that space to T
<[X]>w[B!0]{b[0]>}          # Erase the entire visible part of that line
<[X]^b[T+66]                # Print (the value read from that line)+'B' at (0, 0)

3
就像看着一个人陷入疯狂的血统。
Kzqai 2015年

3

Perl 5,72个字节

@_=split//,<>;($i)=grep$_[$_]eq'^',0..@_;$j+=$_*($k++-$i)for@_;say$j<=>0

3

MATLAB 91、57、55倍频程,50字节

我没想到会进一步打高尔夫球,但是切换到Octave可以节省5个额外的字节!哇,这花了时间...

@(x)(s=mod(+x,16))*[1-(i=find(s>9)):nnz(x)-i]'*inf 

它输出-Inf, NaN, Inf用于L, B, R分别。

测试套件!

说明:

这绝对是很难阅读的代码,但是我会尽力解释。我将在代码块说明和文本之间切换。

@(x)                 % Anonymous function that takes a string x as input
           +x        % Convert the string into a numeric array, 
                     % where each character is represented by its ASCII-value
       mod(+x,16)    % Takes this string modulus 16, to make spaces (ASCII 32) equal 0 
    (s=mod(+x,16))   % Assigns this numeric array to s, thanks to Octave's awesome 
                     % inline variable assignment possibility
    (s=mod(+x,16))*  % Multiply s by the vector inside the brackets    

让我们看看括号内发生了什么:

[1-(i=find(s>9)):nnz(x)-i]
      find(s>9)             % The only value in the vector s that's larger than 9, 
                            % after the modulus is ^, (it's now 14)             
   (i=find(s>9))            % Assign the position of `^` to the index variable i

这有点棘手:

[1-(i=find(s>9)):nnz(x)-i]

梯子两边的数字必须乘以与插入符号之间的距离。如果我们在左侧使用负数,在右侧使用正数,我们可以简单地对向量求和以查看哪一侧最重。

假设输入字符串是:'321^ 12'。我们需要以下内容:3*(-3)+2*(-2)+1*(-1)+1*3+2*4。由于尖号位于第4位1-i,因此我们在方括号内创建的矢量从处开始,在这种情况下为-3。它以1 nnz(x)-i为增量递增。我们可以使用nnz(x)代替numel(s),因为它x是一个不包含零的字符串。

因此:

[1-(i=find(s>9)):nnz(x)-i]
ans =
  -3  -2  -1   0   1   2   3   4

现在,我们可以进行逐元素相乘s.*[...],并求和。但是,由于我们有两个向量,因此我们也可以对它们s进行转置[...]并使用矩阵乘法计算和:

(s=mod(+x,16))*[1-(i=find(s>9)):nnz(x)-i]'

这给我们提供了一个负数(表示左侧更重),一个零(表示平衡)或一个正数(表示右侧更重)。与其使用的朴素方法sign(...)inf不如将它乘以,这将分别为我们-InfInf左,右。我们得到NaN0*inf,因为它是不确定的。

这为三个可能的结果提供了三个截然不同的价值。



2

JavaScript,146字节

s=>{a=[0,0];d=s.split`^`;for(j=0;j<2;j++)for(i=0;i<d[j].length;i++)a[j]+=d[j][i]*(j==0?d[j].length-i:i+1);alert(a[0]==a[1]?'B':a[0]>a[1]?'L':'R')}

相当大。

演示


使用ES6,您可以节省很多字节。整体function t(s){可能成为,t=>{并且split('^')可能成为split`^`
Downgoat

@Vɪʜᴀɴ您可能是说s => {?
nicael 2015年

哦,是的,对不起,这就是我的意思
Downgoat

@Ypnypn -6个字符:)
nicael

2

Ruby,111108字节

->s{l,r=s.split'^';v=->x{x.chars.map.with_index{|c,i|c.to_i*(i+1)}.reduce:+};%w(B L R)[v[l.reverse]<=>v[r]]}

说明

总结每一边每个数字的加权值。然后,它使用ruby宇宙飞船运算符提供两侧的等式/不等式的1,0,-1,这是具有正确输出的数组的索引。


2

PowerShell,83 73字节

param($b)$i=-$b.indexOf('^');[char[]]$b|%{$x+=$i++*"$_"};[math]::Sign($x)

感谢TessellatingHeckler的高尔夫运动。

使用与下面的旧代码本质上相同的算法,但是这里我们一次遍历输入字符串中的字符,而不是遍历索引,这节省了一些字节。当算法达到时,仍然会抛出相同的错误消息^-不影响STDOUT。


以前

param($a)1..$a.length|%{$x+=+"$($a[$_-1])"*($_-$a.indexof('^')-1)};[math]::Sign($x)

使用与Dendrobium出色答案相同的出色算法,因此-1 / 0 / 1如果输入为,则使用相同的输出left-heavy / balanced / right-heavy

啊。因为长的铸造怪癖功能,PowerShell有。这里最相关的是如何char乘以int函数。将结果的数组索引string作为char对象。char在乘法运算之前,PowerShell将转换为其对应的ASCII值(而不是文字值)。因此,$a='012'[0];[int]$a*2结果类似96

这意味着我们需要将其重新铸造为字符串。但是,简单地做string时间int会使我们string重复很多次。例如,$a='0';$a*2将导致00

这意味着我们需要转换char回为一个string之前重新 -casting为int,然后乘可能发生,才将其添加到我们的累加器$x

将其与冗长的迭代字符串的方式以及.NET调用以输出符号的方式相结合,我们得到了很长的代码。

NB-当它到达^字符串时,这将引发一个壮观的错误,表明它无法将其转换为int。不会影响STDOUT。


我有param($b)$i=-$b.indexOf('^');[char[]]$b|%{$x+=$i++*+"$_"};[math]::Sign($x)74个字节。这花费了很长时间,并且尝试了几种方法。math :: sign看起来很长,但我看不出有什么方法可以改善这一点。
TessellatingHeckler 2015年

@TessellatingHeckler当然,遍历字符本身而不是索引……是有道理的!我使用PowerShell的隐式强制转换$i++*+"$_"等效于$i++*"$_"if $i是一个int。
AdmBorkBork 2015年

1

CJam,29个字节

l_'^#\"^ "'0er'0f-_,,@fm.*:+g

在线尝试

结果是-1左重,0平衡,1右重。

这似乎有些冗长,但是我尝试了很多替代方法,它们最终都在29到33个字节之间。一个问题是我找不到将字符串转换为将自动导致空格为0的值的方法。因此,我最终用'0个字符显式替换了空格,这显然增加了代码的长度。

尝试的替代方法:

  • 在'^处分割字符串,将第一个反转,然后计算两者的加权值。
  • 使用ee运算符将索引添加到值列表。
  • 与其从每个索引中减去脱字符号的位置,不计算减法的点积,然后从结果中减去脱字符号乘以字符串长度。

说明:

l         Get input.
_'^#      Copy and find caret position.
\         Swap input back to top.
"^ "'0er  Replace caret and spaces with '0.
'0f-      Subtract '0 from all characters, to get integer values.
_,,       Build index array with same length.
@         Rotate caret position to top.
fm        Subtract it from all indices.
.*        Calculate element wise product of two vectors.
:+        Add up the element products to get dot product.
g         Signum.

1

Python 3,196114字节

r=0
I=list(input())
p=I.index("^")
i=0
for E in I:
 if E.isdigit():r+=int(E)*(p-i)
 i+=1
print('BLR'[(r>0)-(r<0)])

常规代码:

total = 0

inp=list(input())
ful_index=inp.index("^")

i=0
for num in inp:
    if num.isdigit(): total += int(num) * (ful_index - i)
    i+=1

print('BLR'[(total>0)-(total<0)])

说明:

  1. 从生成数字列表和支点stdin
  2. 对于每个数字,将支点乘以数字到变量的距离再加上总数(左数为负,右数为正)。
  3. 根据结果​​打印正确的字母(如果相等则为B,如果大于零则为L,如果小于零则为R)。

非常感谢@ThomasKwa削减了82个字节(超过40%)!


一个简单的15个左右的字节:print('LBR'[(B>D)-(B<D)])用于结尾和B=D=0开头。
lirtosiast

不,甚至更好:不要分别跟踪左右。取而代之的是将负数乘以负数^。那也可以节省您abs()
lirtosiast

1

C,140个139 138 134 100字节

返回:

  • 1 =左
  • 2 =平衡
  • 0 =右
k;main(int x,char**a){char*n=a[1],*g=n;for(;*n^94;++n);for(;*g;++g)k+=(*g&15)*(n-g);return!k?2:k>0;}

跑:

./see-saw "11   ^9"
echo $?
2

由于我们有ASCII:

SPACE = 0x20
    0 = 0x30 ... 9 = 0x39

我们得到:

0x20 & 0x0f = 0
0x30 & 0x0f = 0
0x31 & 0x0f = 1
0x32 & 0x0f = 2
... etc.

然后按因子距离求和^


1

SpecBAS-140字节

1 INPUT b$: LET t=0,p=POS("^",b$),l$="RBL"
2 FOR i=1 TO LEN b$
3 IF b$(i) IN ["1" TO "9"] THEN INC t,(p-i)*VAL b$(i)
4 NEXT i
5 TEXT l$(2+SGN t)

t是连续的总数,当字符位置大于克拉位置时,该值为负。最后,它查看total是负数,零数还是正数,并打印R,B或L的相应字符。

我可以像其他答案一样通过输出-1、0或1来节省一些字节。


1

Java,83个字节

l->{int s=0,l=0;for(char c:l)if(l<1)s-=c-48;else s+=c-48;return s<0?-1:(s>0?1:0));}
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.