レバーシミュレーター2015


46

なぜシミュレーターなのか?

最近の子供たちは、実際にシーソーに箱を積み込んだり、物理的な物体のバランスをいじったりする時間も野心もありません。私のモデルによれば、これはレバーシミュレーターのためのソフトウェア市場に多くの余地を残します。

プログラミングヘルプ募集

私はそのようなゲームの特許を申請中です(保留中)が、ゲームロジックを書くために専門のプログラマが必要です。私の理解では、最終的なプログラムのバイト単位サイズに基づいてプログラマーに報酬を支払うことは標準的な習慣です。このように、私はこの有利な契約を最低入札者に授与します。

仕様

レバーとは、支点によってバランスが保たれた一連の箱または空の空間です。各ボックスには、特定の重みがあるものを経由9、スペースには重みがありません。ご存知のように、レバー上のボックスの重量は、そのボックスが支点からどれだけ離れているかに直接比例します。4支点から3番目のスペースにある重量の箱は12、レバーのその側に有効な力の単位を提供します。

入力レバーが与えられた場合、レバーが左に傾くか、右に傾くか、完全にバランスが取れているかを出力するプログラムが必要です。

I / Oガイドライン

  • あなたは私のためにプログラムを書くでしょう。
  • 入力には1行のテキストが含まれます。
  • 入力はstdin、1つのコマンドライン文字列から、または1つのコマンドライン文字列として取得されます。
  • ボックスは、文字「1」から「9」で表されます。これらの文字は、それぞれの重みを表します。空のスペースはスペース「」で表されます。支点はキャレット「^」で表されます。

サンプル入力レバーは次のようになります。 8 2^ 941

このレバーは完全にバランスが取れています。 (4*8) + 0 + 0 + (1*2) == 0 + (2*9) + (3*4) + (4*1) == 34

  • 先頭または末尾のスペースはありません。末尾の改行はありません。
  • 不正な入力を処理する必要はありません。入力には常に1つの支点があり、数字とスペースのみがあります。
  • 出力は、レバーが左に重いか、右に重いか、バランスが取れているかを示します。
  • プログラムには、整形式の入力から生じる可能性がある正確に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^または^?(できると仮定)
ルニウム

ああ仕様の穴は、ええ、私は側面が空にすることができますと仮定したい
turbulencetoo

7
私はちょうど1オフセット3または4でオフセット11はおそらく9でバランスさせることができるか疑問いくつかの時間を秒を過ごした
ジェームズ・ソープ

回答:


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つが生成され-1,0,1ます。キャラクター^はウェイト14を持つように計算されますが、ピボット上にあるので問題ではありません。

18バイトのPythポート Maltysenによって:

._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.herokuapp.com /… 18バイトが必要な場合に投稿できるメソッドを使用したPythプログラムです。自分で投稿するのは適切ではないと感じました。
マルティセン

@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=を省略して、匿名関数を生成すると言うことは一般的なコンセンサスです。(-2バイトFYI)
コナーオブライエン

5

Japt、22バイト

JaptJa vaScri ptの短縮バージョンです。通訳

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

-1for L0for B、および1for を返しますR

使い方

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)×(⍳⍴⍵)-⍵⍳'^'}

ルールを読み直した後、これをの-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左が右より重い場合(L
  • 0左が右と同じくらい重い場合(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

pb 349 329バイト

^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を減算して比較することもできません。

  • 2つの合計の合計を見つけます。
  • 何も使用されていない行で、それだけ右に移動します。
  • X = 0になるまで、左に移動して「L」を配置します。
  • X = 0に「B」を配置します。
  • 2つの合計の左に移動します。
  • X = 0に達するまで、右に移動して「R」を配置します。

次に、X =(左側-右側)に移動するだけで、答えが得られます!その行のすべてを削除してクリーンアップし、(0、0)で見つかった値を出力します。

...しかし、少し短い方法があります。「L」、「B」、「R」を使用する代わりに、「B」の値を使用して、印刷時に「B」を追加し直します。そうすれば、X = 0に「B」を配置する必要がなくなり、既にあった0のままにしておくことができます。唯一の問題は、これを行うと、プログラムがウォッチモードで非常に間抜けになることです。'L'-'B'==76-66==10=='\n'。突然大量の改行が印刷され、何が起こっているかを追跡することが不可能になるまで、すべてが正常に機能しているように見えます:Dコンソール。

^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
男が狂気に陥るのを眺めるようなものです。
クズカイ

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, InfL, 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、です。それはに上がるnnz(x)-i1ずつ。ゼロのない文字列であるため、のnnz(x)代わりに使用できます。numel(s)x

したがって:

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

これで、要素ごとの乗算を実行しs.*[...]、この合計を取得できます。ただし、2つのベクトルsがあるため、転置によって複数[...]の値を計算し、行列乗算を使用して合計を計算することもできます。

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

これは、左側が重いことを意味する負の数、バランスが取れていることを意味するゼロ、または右側が重いことを意味する正の数を与えます。代わりの単純なアプローチを使用してのsign(...)、我々は乗算、それによってinf、私たちのいずれかを与えるであろう-Infか、Inf左用と右のそれぞれ。未定義なので、を取得NaN0*infます。

これにより、3つの可能な結果に対して3つの異なる値が得られます。


2

𝔼𝕊𝕄𝕚𝕟、22文字/ 38バイト

МŴ⟬ïĊ⇀$+˜_*(ã-ïÿ⍘^),0⸩

Try it here (Firefox only).


2
-1これは、バイトカウントではなく文字カウントを最適化しています
Mego

それがgoが@Megoのために構築されたものです。
ママファンロール

3
作成目的に関係なく、スコアリングはバイト単位です。
メゴ

という事は承知しています。
ママファンロール

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 => {?
ニカエル

そうそう、ごめん、それが私が意味したことです
-Downgoat

@Ypnypn -6文字:)
nicael

2

ルビー、111の 108バイト

->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に感謝します。

本質的には以下の古いコードと同じアルゴリズムを使用しますが、ここでは、インデックスを繰り返し処理するのではなく、入力文字列の文字を1つずつ繰り返し処理します。アルゴリズムが到達しても同じ壮大なエラーメッセージをスローし^ます-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が持っているキャスティングの奇妙な機能のために長い。ここで最も適切なのはcharint関数の乗算方法です。オブジェクトの配列インデックスを取得stringcharます。PowerShellは、char乗算の前に(リテラル値ではなく)対応するASCII値に変換します。したがって、次のような$a='012'[0];[int]$a*2結果になり96ます。

つまり、文字列として再キャストする必要があります。しかし、単純にやっstring回は、int私たちに与えstring繰り返さことを何回も。たとえば、$a='0';$a*2結果はになり00ます。

これは、asをキャストcharするstring前にaとしてキャストする必要があることを意味します。そうすると、アキュムレータに追加する前に乗算が発生する可能性があります。int$x

文字列を反復処理する長い方法と、符号を出力する.NET呼び出しを組み合わせて、かなり長いコードを取得します。

NB-これは^、文字列に達すると、それをに変換できないことを示す壮大なエラーをスローしますint。STDOUTには影響しません。


私が持っているparam($b)$i=-$b.indexOf('^');[char[]]$b|%{$x+=$i++*+"$_"};[math]::Sign($x)74のバイトで。これには長い時間がかかり、いくつかのアプローチが試みられました。math :: signは非常に長く見えますが、そのビットを改善する方法がわかりません。
TessellatingHeckler

@TessellatingHeckler確かに、インデックスではなくキャラクター自体を反復処理するのは理にかなっています!PowerShellの暗黙的なキャストを使用して追加バイトをゴルフした場合は、if がintに$i++*+"$_"相当します。$i++*"$_"$i
AdmBorkBork

1

CJam、29バイト

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

オンラインで試す

結果は-1、左ヘビー、0バランス、1右ヘビーです。

これは少し長いように見えましたが、私は多くの代替手段を試しましたが、それらはすべて29バイトから33バイトの間でした。1つの問題は、文字列を、スペースが自動的に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、196 114バイト

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

82バイト(40%以上)をトリミングしてくれた@ThomasKwaに大いに感謝します!


簡単な15バイト程度:print('LBR'[(B>D)-(B<D)])終了時とB=D=0開始時に使用します。
リトシアスト

いいえ、さらに良いことです。左右を別々に追跡しないでください。代わりに、の左側の数値に負の距離を掛け^ます。それabs()もあなたを救います。
リスト管理者

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が負、0、または正であるかどうかを確認し、R、B、またはLの対応する文字を出力します。

他のいくつかの回答のように、-1、0、または1を出力するだけで、数バイトを削ることができます。


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