我会给小费吗?


36

总览

给定一个3行的字符串,请找出结构是落在左侧,平衡还是落在右侧。

输入结构

您可以将结构想象为金属棒,顶部有填充物,所有材料都平衡在垂直棒的顶部。

1  7 4        a
===============
        |

第一行是项目。每一项的权重均以字符减去32的ascii值进行计算。(不考虑32以下的字符,空格的权重为0)。请记住,物品在杆上的作用力是其重量乘以到枢轴点的距离。

第二行是杆。杆的每个长度自身重1个单位。该行完全等于符号(=)。

第三行是枢轴点。它可以放置在任何地方,并由多个空格和一个竖线(|)字符表示。

例子

输入:

=====
  |

输出:余额

输入:

=====
   |

输出:向左倾斜

输入:

    %
=====
   |

输出:天平(因为%重量足以抵消杆左侧的重量)

输入:

 a
=======
   |

输出:向右倾斜(因为a右侧的距枢轴点更远)

输入:

1  7 4        A
===============
        |

输出:向左倾斜

输入:

1  7 4        a
===============
        |

输出:向右倾斜(小写字母很重!)

输入:

            $ ~
===============
             |

输出:余额

笔记

  • 允许尾随空格,不允许前导空格。
  • 只要左,平衡和右有3个不同的输出,您的程序就可以以您喜欢的任何格式输出。
  • 您的程序必须接受显示为输入的格式。


程序是否可以将三行作为三个单独的字符串(例如,作为函数的三个参数或作为三个元素的列表)?
notjagan

@notjagan输入必须是由换行符分隔的单个字符串。
达菲(Daffy)

相关的,可能的欺骗。
xnor

@xnor不是骗子,因为该问题仅处理大写字母,其目标是找到关键点。我的问题是所有大于等于32的ASCII字符,我的提供了枢轴,并询问结构是否会倾覆。本质上是您链接的反向链接。
达菲

Answers:


8

的JavaScript(ES6),116个 111 108 106字节

通过eval(array.join`+`)而不是通过加-5字节array.reduce()
-3字节(默认为1而不是32 - 31)允许删除括号。
-2个字节,因为枢轴点是最后一行的长度-1

(s,[t,r,b]=s.split`
`)=>Math.sign(eval([...r].map((_,i)=>(t.charCodeAt(i)-31||1)*(i-b.length+1)).join`+`))

分别为左,平衡或右输出-101。最终类似于Chas Brown的python答案,因此功劳很大。

如果使用填充第一行以匹配标尺的长度,则可以节省4个字节
(31-t.charCodeAt(i))*(b.length+~i)

测试片段

包括附加的输出(Left/ Balanced/ Right)和数字。

f=
(s,[t,r,b]=s.split`
`)=>Math.sign(eval([...r].map((_,i)=>(t.charCodeAt(i)-31||1)*(i-b.length+1)).join`+`))
<textarea id=I rows=3 cols=20></textarea><br><button onclick="O.value=I.value?`${x=f(I.value)} (${['Left','Balanced','Right'][x+1]})`:''">Run</button> <input id=O disabled>

另一种106字节方法

(s,[t,r,b]=s.split`
`)=>Math.sign(eval(r.replace(/./g,(_,i)=>"+"+(t.charCodeAt(i)-31||1)*(i-b.length+1))))

我们创建了一个数字字符串,每个数字都以前缀,而不是join+s 上放置数组+。领导者+被忽略了。


1
我认为(b.length+~i)可能有助于节省一个字节。(而且我也不明白你为什么要这么做||1。)
Neil

1
@Neil b.length+~i返回的负数i-b.length+1;如果我可以否定其他部分,那可能会有所帮助。至于||1,那是因为我假设第一行没有填充以匹配杆的长度,所以t.charCodeAt(i)它将返回NaN到第一行的末尾。
贾斯汀·马里纳

我没有尝试过非填充测试用例。感谢您的解释。
尼尔

3

Python 2中112个 110字节

def f(s):w,b,p=s.split('\n');return cmp(sum((ord((w+' '*-~i)[i])-31)*(i-p.find('|'))for i in range(len(b))),0)

在线尝试!

编辑:最终设法消除了enumerate和仅rjust2个字节...嗯!

取一个字符串;输出分别为-1,0或1(分别表示左落,余额,右落)。

112字节的第一遍是:

def f(s):w,b,p=s.split('\n');return cmp(sum((ord(c)-31)*(i-p.find('|'))for i,c in enumerate(w.rjust(len(b))),0)

(ord(c)-31)让我花了一段时间才意识到这实际上是在将杆本身的重量与物品结合在一起。非常聪明!
达菲

1
根据meta,您可以returnprint-1字节替换(尽管它不能与当前的TIO代码很好地配合使用)。
notjagan

3

Haskell,212 171字节(如果将输入作为一个字符串则为188)

o!p=map(fst)(zip[p-0,p-1..]o)
x#p=sum(zipWith(\c w->(max(fromEnum c-32)0)*w)x(x!p))+sum(x!p)
x?c=length(takeWhile(==c)x)

171个字节的变体

r a b c=signum(take(b?'=')(a++repeat ' ')#(c?' '))

188个字节的变体

x%y=lines x!!y
r i=signum(take(i%1?'=')(i%0++repeat ' ')#(i%2?' '))

说明

o!p=map(fst)(zip[p-0,p-1..]o)        Creates weights coefs list. 
                                     o - list, p - pivot position
                                     for list "abcdf" and p=3 (pivot under 'd')
                                     outputs [3,2,1,0,-1]

x#p                                  Calculates total balance
                                     x-list of "objects" on lever, p-pivot place
  sum(zipWith                        sum of zipped lists
   (\c w->(max(fromEnum c-32)0)*w)   weight of ascii "object" times
                                     distance from pivot
    x(x!p))                          x-ascii objects, 
                                     (x!p)-distances list(weight coefs)
  +sum(x!p)                          balance of lever ("==") itself

x?c=length(takeWhile(==c)x)          length of list before non c element met
                                     used to find '|' position
                                     and length of "===" lever
                                     before right whitespaces met

r a b c=                             Sums it all up =)
                                     a-ascii objects, b-lever, c-pivot line
   signum(                           1-tips left, 0-balance, -1-tips right
     take(b?'=')(a++repeat ' ')      takes all object on lever 
                                     plus whitespaces up to length of the lever
      #                              calculate the balance
       (c?' ')                       determine place of pivot

1
您可以使用fromEnum代替ord并删除importc可以简化为c p=max(ord p-32)0(或使用fromEnum),并且仅使用一次就可以对其进行内联。
nimi

或者,您可以在标题中添加(Lambdabot),这将导入您所需的几乎所有内容,请参见此处
ბიმო

1
c甚至可以进一步简化该功能(不考虑32以下的字符)c p=ord p-32。也p基本上是length(减1),因此p x=length x-1将工作太(你可以内联太)。也请看一下我的解决方案,如何使用signum-您可以为B,L,R r o l s = signum $ 2 * z ...退货0,1,-1
ბიმო

1
除此之外,该解决方案似乎无法通过测试用例,[3,4,7]并且使用3个String而不是1个String。(请参阅lines)。
ბიმო

1
是一个应用了一些技巧的版本(为您节省29个字节;)。
ბიმო

2

果冻,30个字节

O_31×J_¥A+\sṪ€µ÷ḢṪ_2Ṡ
ỴṪLç@ỴḢ$

测试套件

输出0表示平衡,输出1表示右,-1表示左。

怎么运行的

O_31×J_¥A+\sṪ€µ÷ḢṪ_2Ṡ - helper function. Arguments position of pivot and first line
O                        - char codes of first line
 _31                     - subtract 31 to get weight
    ×                    - elementwise product with:
     J_¥                 - distances from the pivot
        A                - absolute value
         +\              - cumulative sum
           s             - split to get [[...,left weight],...,[..., right + left weight]]
            Ṫ€           - last element of each sublist: [left weight, ... right weight]
              µ÷Ḣ        - get ratio of each element over left weight: ratio n indicates
                              right + left = n × left ===> right = left if n = 2
                 _2      - subtract 2: positive is right>left and negative is right<left
                   Ṡ     - return the sign of this


ỴṪLç@ỴḢ$              - main link. Argument: 3 line string.
   ç@                  - apply helper function with arguments:
Ỵ                        - split by linefeeds
 Ṫ                       - last line
  L                      - length (returns position of pivot)
       $               - and
     Ỵ                   - split by linefeeds
      Ḣ                  - first line              

2

果冻,24字节

ṪO_31
ỴµṪLạЀṪL$×Çṣ0S€IṠ

在线尝试!

-1用于左倾,0用于平衡,1用于右倾(完整程序)。
[-1]用于左倾,[0]用于平衡,[1]用于右倾(功能)。

第一行必须有尾随空格,最后一行不能有尾随空格。

说明(我们从底线开始):

首先,我们正在处理单个行,因此我们需要以某种方式获取它们。那是工作。然后,我们需要\n将输入的-split版本当作原始输入一样对待,因此我们µ需要使单链应用于当前值。

现在我们开始真正的工作,而我们的第一项工作将是计算权重因子。本质上,这是一个范围[从最左端到枢轴的距离..0 ..从枢轴到最右端的距离]。首先,我们必须找到枢轴的从1开始的索引,该索引实质上是没有尾部空格的最后一行的长度。因此,我们将原始列表的最后一行(枢轴线)用弹出,因为我们不再需要它,然后用取其长度L。然后,我们需要取杆的长度,为此,我们对最后一条线(杆线)执行相同的操作ṪL$。最后,要获取范围,请映射| x - y | 到[1..rod length],其中x是枢轴索引,y是我们映射到的列表的每个元素。我们使用ạЀ,其中计算| x - y | Ѐ使一个范围为1直到并包括所述杆的长度。现在我们有了想要的范围。

之后,我们必须将代表一根棒的每个整数乘以其相应的权重。要计算权重,我们使用Ç,转到代码的第一行。我们用剩下的行用,其字符代码用O,然后使用,其中x是每个字符代码来计算x -31。然后,我们为权重1(0 +杆件= 1),权重2(1 + 1)等分配空间。我们完成了顶行,因此现在将返回权重列表,将其与相应的权重相乘用表示杆件的整数。_31!Ç×

之后,我们ṣ0在枢轴点上用分割,用0表示(因为那里的任何权重都不会影响结果),从而形成形式为[[第一个权重,第二个权重...正好在枢轴之前的权重]的列表,[枢轴刚过之后的重量,之前...最后一个重量之后的重量]]。这些列表代表杆的左右两侧。现在,我们对每个列表求和,S€以获取每一侧的总权重,并使用Idelta,如果左侧较重,则为负;如果等权重,则为零;如果右侧较重,则为正。因此,为了正确使用此最终结果以使我们受益,我们使用标记


2

APL(Dyalog),43字节*

{×(¯31+⎕UCS⊃⍵)+.×(⍳≢⊃⍵)-'|'⍳⍨⊃⌽⍵}⎕TC[2]∘≠⊆⊢

在线尝试!

⊆⊢ 将参数划分为

⎕TC[2]∘≠ 从不同的2 Ť端子Ç ONTROL字符(换行)**

{} 在字符串列表中应用以下匿名函数:

⊃⌽⍵ 在反向列表的第一个字符串中(即最后一个)

'|'⍳⍨ 找出枢轴点的the ndex

()- 从以下列表中减去:

  ⊃⍵ 第一个字符串

   它的长度

   所有ɩ那ndices

()+.× 具有这些权重和以下值的加权总和:

  ⊃⍵ 第一个字符串

  ⎕UCS 在代码点ü niversal Ç haracter 小号

  ¯31+ 加上负三十一(所需偏移量为32,杆为一)

× 的信号


*对于每个字符1个字节,请{×(¯31+⎕UCS↑⍵)+.×(⍳≢↑⍵)-'|'⍳⍨↑⌽⍵}⎕TC[3]∘≠⊂⊢与一起使用⎕ML←3在线尝试!
** ⎕TC已弃用,此处仅用于打高尔夫球。在生产代码中,应使用⎕UCS 10


2

Haskell(Lambdabot),142个字节

l=length
g[a,c,b]=splitAt(l b)$a++(' '<$[1..l c-l a])
k e=sum$zipWith((*).(-31+).ord)e[1..]
f=signum.uncurry(-).(k.drop 1.reverse***k).g.lines

在线尝试!

非高尔夫版本:

-- for readability, allows reading top-down/left-right
(.>) = flip (.)

ungolfed =
     lines                                 -- separate out lines into..
  .> (\[a,b,c] ->                          -- a,b,c (first,second,third)
                                           -- ' ' pad the first line & split on pivot
       splitAt (length c) (a ++ replicate (length b - length a) ' ')
     )
  .> (weight.drop 1.reverse *** weight)    -- reverse left half, drop element above pivot & get weight for both
  .> uncurry (-)                           -- subtract right from left
  .> signum                                -- get sign

-- get ord of the character subtract 31 ('=' char from bar),
-- then multiply with scales ([1..]) and sum it all up
weight es = sum $ zipWith (ord .> subtract 31 .> (*)) es [1..]

2

Python 2,90个字节

def f(s):L=len(s)/3;print cmp(sum((ord(s[i])-31)*(i-s[-L:].find('|'))for i in range(L)),0)

期望将输入行填充(用空格)到正确的长度。输出-1跌倒留下0用于平衡,并1下降权

在线尝试!


94字节

对于+4个字节,我们可以有一个版本,该版本使用while循环,需要剥离线而不是填充线:

def f(s):
 i=r=0
 while''<s[i]:r+=(ord(s[i])-31)*(i-s[-3::-1].find('='));i+=1
 print cmp(r,0)

在线尝试!


1

Ruby,543字节

def willittip(s)
leftw=0;
rightw=0;
arr=[];
fields=s.split("\n")
pos=fields[2].index("|")
fields[0].split("").each do |i|
arr << i.ord-32
end
arr[pos+1..-1].each_with_index do |x,y|
rightw=rightw+1
if x>0
if pos>0
rightw=rightw+x*(pos-y).abs
else
rightw=rightw+x
end
end
end
arr[0..pos-1].each_with_index do |x,y|
leftw=leftw+1
if x>0
if pos>0
leftw=leftw+x*(pos-y).abs
else
leftw=leftw+x
end
end
end
if leftw==rightw
return "Equal"
elsif leftw<rightw
return "Right"
elsif leftw>rightw
return "Left"
end
end

10
欢迎来到PPCG!:D应对代码高尔夫球的目标是使您的代码尽可能的小。您可以通过将所有变量和函数名称设为单个字符,并尽可能删除空格来减小代码大小。
达菲(Daffy)

1

C(gcc),106107 121 123 124 129 131 个字节

c,b,l,i;f(char*a){l=strlen(a)/3;for(i=b=c=0;32/a[l*2+c];++c);for(;i<l-1;b+=(a[i]-31)*(i++-c));a=b>0?2:!b;}

返回0表示左下落,返回1表示平衡,返回2表示右下落。

要求所有三行都具有相同的长度,并最后\n确定字符串的长度。

在线尝试!


1

Mathematica,91岁 92 个字节

Sign[(v=(g=ToCharacterCode)@#&@@(d=#~StringSplit~"
")-31).(Range@(l=Length)@v-l@g@Last@d)]&

第一行与杆的长度应相同。第三行不应包含尾随空格。

返回-1、0、1表示左下降,平衡和右下降。


1

C#(.NET Core)127 95 90 + 18 = 108字节

对于此功能,第一行必须正确填充空格,使其长度与杆的长度相同,第三行必须没有试验空格。允许此条件(请参阅问题注释)。

s=>s.Split('\n')[0].Select((c,i)=>(c-31)*(i-s.Split('\n')[2].Length+1)).Sum().CompareTo(0)

在线尝试!

输出:

-1为笔尖向左
0为余额
1为笔尖向右


1

Python 3,217个字节

也可在Python 2.7中使用

def f(s):i,b,p=s.split('\n');c=p.find('|');l=sum((ord(e)-32)*(c-i.find(e))for e in i[:c])+sum(x for x in range(1,c+1));r=sum((ord(e)-32)*i[c:].find(e)for e in i[c:])+sum(x for x in range(len(b[c:])));return(l>r)-(r>l)

对于左侧,返回1;对于右侧,返回-1;如果平衡,则返回零。

可读版本:

def f(s):
    i,b,p = s.split('\n')
    c = p.find('|')

    l = sum((ord(e)-32)*(c-i.find(e))for e in i[:c])+sum(x for x in range(1, c+1))
    r = sum((ord(e)-32)*i[c:].find(e)for e in i[c:])+sum(x for x in range(len(b[c:])))

    return(l>r)-(r>l)

1
您不需要sum([...]),只需拥有sum(...)
Xcoder先生,2017年

@Daffy,这应100%符合您的规范和所有给定的示例输入。如果您同意,请告诉我,以便我进一步优化它。谢谢。
veganaiZe'7

@veganaiZe通过了我所有的测试,看起来不错!:)
Daffy'7

1
i[c:].find(e)可以简化的东西:可以i.find(e,c)使用,根本i,m,n=s.split('\n')不需要s使用,return 2*(r>l) or l>r可以显着降低最终的测试成本(返回值在数值上相等,但是True1False代替0),或者实际上,使用不同的返回集值并按return (l>r)-(r>l)cmp函数的方式返回1、0或-1 。
ShadowRanger

感谢ShadowRanger,Xcoder先生和Daffy!@ShadowRanger我必须坚持使用,i[c:]因为较短的方式导致某些极端情况下的输入产生奇怪的逐个问题(尝试将|精确地放置在中间,在小节上方)。
veganaiZe

1

PHP,105字节

for([$a,$b,$c]=explode("
",$argn);$b[$i];)$w+=(strpos($c,"|")-$i++)*8*(max(1,ord($a[$i])-31));echo$w<=>0;

打印-1/ 0/ 1表示左/平衡/右。与管道一起运行-nR在线尝试

分解

for([$a,$b,$c]=explode("\n",$argn); # import input
    $b[$i];)                        # loop through bar
    $f+=                                # add to force:
        ($i-strpos($c,"|"))             # distance (<0 if left, >0 if right of pivot)
        *8                              # *8
        *(max(1,ord($a[$i++])-31));     # *weight
echo$f<=>0;                         # print -1 if $f<0, 1 if $f>0, 0 if $f==0

1

木炭,31字节

A⁰ξFLθA⁺ξ×⁻ι⌕ζ|⁻℅§θι³¹ξI⁻›ξ⁰‹ξ⁰

在线尝试!链接是详细版本的代码。输出0表示平衡,或-1或1表示左或右下降。编辑:木炭的更改现在意味着≔ΣEθ×⁻κ⌕ζ|⁻℅ι³¹ξI⁻›ξ⁰‹ξ⁰可以使用24个字节:在线尝试!链接是详细版本的代码。注意:这两个答案都需要填充输入,但是可以调整为接受未填充输入,但要花3个字节:≔⁰ξFLη≔⁺ξ×⁻ι⌕ζ|⁻℅§◨θLηι³¹ξI⁻›ξ⁰‹ξ⁰ 在线尝试! ≔ΣE◨θLη×⁻κ⌕ζ|⁻℅ι³¹ξI⁻›ξ⁰‹ξ⁰ 在线尝试!链接指向详细版本的代码。


您可能要提一下,这希望输入行被空格填充到正确的长度,因此填充的输入可能无法正常工作。
FlipTack

@FlipTack更妙的是,我设计了可以接受未填充输入的版本。
尼尔,
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.