Dotty文字列の評価


25

文字.とのみを含む奇数長の文字列を取り込むプログラムを作成し:ます。最初は空のstackを使用して、次のようにこの文字列から数値を生成します。

文字列内のすべての文字cについて(左から右へ)...

  • 場合cがあり.、スタックが2つの未満の要素を有し、スタックに1を押してください。
  • 場合cがあり.、スタックは、2つの以上の要素を有し、スタックから2つのトップの値をポップし、スタックにその和を押します。
  • 場合cがあり:、スタックが2つの未満の要素を有し、スタックに2を押してください。
  • 場合cがあり:、スタックは、2つの以上の要素を有し、スタックから2つのトップの値をポップし、スタックにそれらの製品を押し出します。

結果の数値は、スタックの一番上の値です。プログラムは、この番号を標準出力に出力する必要があります(オプションの末尾の改行を使用)。

(少しの分析では、文字列の長さが偶数でない限り、残っている数字は1つだけであることが示されています。そのため、これらは無視されます。実際、スタックには2つ以上の要素がありません。)

たとえば、の番号::...:.:.は9です。

  2   1   2   2    /______ stack just after the character below is handled
2 2 4 4 5 5 7 7 9  \
: : . . . : . : .  <-- string, one character at a time

健全性チェックとして、長さ1、3、および5のすべての文字列の数値を次に示します。

. 1
: 2
... 2
..: 1
.:. 3
.:: 2
:.. 3
:.: 2
::. 4
::: 4
..... 3
....: 2
...:. 4
...:: 4
..:.. 2
..:.: 1
..::. 3
..::: 2
.:... 4
.:..: 3
.:.:. 5
.:.:: 6
.::.. 3
.::.: 2
.:::. 4
.:::: 4
:.... 4
:...: 3
:..:. 5
:..:: 6
:.:.. 3
:.:.: 2
:.::. 4
:.::: 4
::... 5
::..: 4
::.:. 6
::.:: 8
:::.. 5
:::.: 4
::::. 6
::::: 8

バイト単位の最短プログラムが優先されます。Tiebreakerは以前の投稿です。

  • 入力は常に有効であると想定できます。つまり、長さが奇数の文字列のみが含まれている.と仮定でき:ます。
  • プログラムを作成する代わりに、有効な文字列を取り込んで、生成された数値を出力または返す関数を作成できます。

5
史上最高のミニマリストイコライザー。
dberm22

回答:


13

CJam、27 24 23 22バイト

q{i]_,+~3<-"1+2* "=~}/

かなり簡単です。私は質問で言及されたスタックとしてCJamのスタックを使用します;)

アルゴリズム

最初は、ASCIIコードを見てみましょう.とします:

'.i ':ied

[46 58]

CJamではインデックスが折り返されるため、これらの値を直接使用して目的の操作を取得できるかどうかを確認できます。

'.i4% ':i4%ed

[2 2]

したがって、4文字の操作文字列でASCIIコードを単純に使用することはできません。他の値を試してみましょう

'.i 10% ':i 10%ed

[6 8]

4つの長さのストリングで

[2 0]

このmod 10操作を使用できますが、コストは2バイトになります。他のことを試してみましょう

'.i5% ':i5%ed

[1 3]

いいですね、今では、スタックサイズ条件から1を減算してインデックスを取得し、スイッチケースとして長さ配列()を0, 1, 2 and 3使用しています。最後のスペースは、長さ5にするための単なるフィラーです。これは、改造操作に比べて1バイト余分になります。5"1+2* "

q{                  }/    e# parse each input character in this loop
  i]                      e# convert '. or ': into ASCII code and wrap everything
                          e# in stack in an array
    _,+                   e# Copy the stack array, take its length and add the length to
                          e# the stack array 
       ~3<                e# unwrap the stack array and check if stack size is less than 3
                          e# 3 because either . or : is also on stack
          -               e# subtract 0 or 1 based on above condition from ASCII code
           "1+2* "        e# string containing the operation to perform
                  =~      e# chose the correct operation and evaluate it

こちらからオンラインでお試しください

cosechyのおかげで1バイト節約


1
一連の操作のスペースは何ですか?
ピーターテイラー

@PeterTaylorは投稿で説明しました。
オプティマイザー

9

> <>(魚)、33バイト

ib%1-i:1+?\~n;
5a*)?*+40.\b%1-0@i

少しのトリック/最適化でかなり簡単です。

説明:

  • 情報:i=入力の-1終わりに達した場合、次の入力文字のコードポイント。a= 10; b= 11; )=>
  • i最初の入力文字のコードポイント、
  • b%1- top_of_stack mod 11 - 1マスク48 ('.') , 56 (':')1 , 2
  • i:1+?\~n; 入力の終わりに達した場合、最後の結果を出力して終了します
  • さもないと:
  • b%1- マスク入力 1 , 2
  • 0@02つの数字の下に押します
  • i5a*)次の入力を読み取り、それをマスクして0 , 1比較する50
  • if 1':')スタックを作成する上位2つの要素を乗算する場合[0 product]
  • 常にスタックを作成する上位2つの要素を追加するか[0 sum][0+product=product]
  • 40.ジャンプ(ループ)して、位置(4,0)、ポイント4i:1+?\~n;

8

Haskell、73 65バイト

スタックが2つ以上の要素を持たないという事実を使用した簡単なソリューション。

[x,y]#'.'=[x+y]
[x,y]#_=[x*y]
s#'.'=1:s
s#_=2:s
f=head.foldl(#)[]

5

C、104バイト

k[2],n;f(char*c){for(n=0;*c;)k[n]=*c++-58?n>1?n=0,*k+k[1]:1:n>1?n=0,*k*k[1]:2,k[1]=n++?k[1]:0;return*k;}

まあ、これは長すぎます。


5

Pyth、25 24バイト

eu?]?.xGHsGtG+GhHmqd\:zY

@isaacgのソリューションを研究して、アイデアを得ました。しかし、私はスタックを使用しています。

オンラインデモンストレーションまたはテストスイート

説明

最初に行うことは、入力文字列を0と1に変換することです。A "."はaに0、aはa ":"に変換され1ます。

mqd\:z   map each char d of input to (d == ":")

次に、この数字のリストを減らします。

eu?]?.xGHsGtG+GhHmqd\:zY
 u                     Y   start with the empty stack G = []
                           for each H in (list of 0s and 1s), update G:
                              G = 
    ?.xGHsG                      product of G if H != 0 else sum of G
   ]                             wrapped in a list 
  ?        tG                 if G has more than 1 element else
             +GhH                G + (H + 1)
e                         take the top element of the stack

4

JavaScript(ES6)、65

スタックの2つのセルのみを使用します。

s [0]に値を入れ始めます。
次に、入力文字列の各奇数位置(0からカウント)で、s [1]に値を入力します。
各偶数位置で、計算(加算または乗算)を実行し、結果をs [0]に格納します。

スタックを忘れて、aとbの2つの変数のみを使用します。

f=s=>[...s].map((c,i)=>(c=c>'.',i&1?b=1+c:i?c?a*=b:a+=b:a=1+c))|a

簡単なテスト

for(i=0;i<128;i++)
{
  b=i.toString(2).replace(/./g,v=>'.:'[v]).slice(1)
  if(b.length&1) console.log(b,f(b))
} 

出力

"." 1
":" 2
"..." 2
"..:" 1
".:." 3
".::" 2
":.." 3
":.:" 2
"::." 4
":::" 4
"....." 3
"....:" 2
"...:." 4
"...::" 4
"..:.." 2
"..:.:" 1
"..::." 3
"..:::" 2
".:..." 4
".:..:" 3
".:.:." 5
".:.::" 6
".::.." 3
".::.:" 2
".:::." 4
".::::" 4
":...." 4
":...:" 3
":..:." 5
":..::" 6
":.:.." 3
":.:.:" 2
":.::." 4
":.:::" 4
"::..." 5
"::..:" 4
"::.:." 6
"::.::" 8
":::.." 5
":::.:" 4
"::::." 6
":::::" 8

-2:f=s=>[(c=s[i]>'.',i&1?b=1+c:+i?c?a*=b:a+=b:a=1+c)for(i in s)]|a
nderscore

少なくとも動作しない私のブラウザでは、@ nderscore。for(i in s)はインデックス以外の追加のプロパティを提供します
-edc65

firefox 37.0.2で動作します。きれいなブラウザタブで実行してみてください。(stub.en.jsに)stackexchangeは、文字列に追加のプロパティを追加するようだ
nderscore

3

Pyth、27バイト

Jmhqd\:zu?*GhHteH+GhHctJ2hJ

スタック?スタックが必要な人。

                       Implicit: z is the input string.
Jmhqd\:z               Transform the string into a list, 1 for . and 2 for :
                       Store it in J.
u            ctJ2hJ     Reduce over pairs of numbers in J, with the
                       first entry as initial value.
 ?    teH               Condition on whether the second number is 1 or 2.
  *GhH                  If 1, update running total to prior total times 1st num.
         +GhH           If 2, update running total to prior total plus 1nd num.

デモンストレーション。


1
天才。その間、スタック(32バイト)を実装しました。:-(
ジャクベ

3

網膜105 75 73バイト

私の最初のRetinaプログラム!(最初に言語を発明したことは言うまでもなく、2バイトを節約してくれたMartinBüttnerに感謝します。)

各行は個別のファイルに入れる必要があります。または、すべてを1つのファイルに入れて-sフラグを使用できます。<empty>表記は、空のファイル/行を表します。

^(a+;)?\.
$1a;
^(a+;)?:
$1aa;
;(a+;)\.
$1
(a+);aa;:
$1$1;
)`;a;:
;
;
<empty>
a
1

mbomb007の答えに触発されましたが、私はやや異なるアプローチを取ります。大きな違いの1つは、ドッティストリングの前にスタックを構築することです(スタックの上部を右に向けます)。これにより、シンボルをインプレースで対応する数値に簡単に変換できます。また、のa代わりにを使用1して、のようなシーケンスのあいまいさの解析を回避するために、最後にのみ交換し$1aます。次のような答えaaaaaaが単項数として受け入れられる場合、最後の2行/ファイルを削除して4バイト節約できます。

説明:

^(a+;)?\.
$1a;

スタック上に0個または1個のアイテム((a+;)?)があり、その後にピリオド(\.)が続く場合に一致します。その場合、ピリオドを置き換えますa;(つまり、1をプッシュします)。

^(a+;)?:(.*)
$1aa;$2

スタックに0個または1個のアイテムがあり、その後にコロンがある場合に一致します。その場合、コロンを置き換えますaa;(つまり、2をプッシュします)。

;(a+;)\.
$1

スタック上にピリオドが2つある場合に一致します。アイテム間のピリオドとセミコロンを削除して、アイテムを追加します。

(a+);aa;:
$1$1;

スタックに2つのアイテムがあり、その上部が2で、その後にコロンがある場合に一致します。コロンと2を削除し、他の数値を2回繰り返して、2倍します。

)`;a;:
;

スタックに2つの項目があり、その先頭が1で、その後にコロンがある場合、正規表現は一致します。コロンと1を削除し、他の数値は変更せずに残します(つまり、1を掛けます)。

)`ループの終わりを示します。文字列に変更が加えられた場合、制御はプログラムの先頭に戻り、置換を再度実行します。文字列の変更が停止した場合、すべてのピリオドとコロンを置き換えました。残りはすべてクリーンアップです...

;
<empty>

残ったセミコロンを削除します。

a
1

すべてのaを1に変換します。繰り返しますが、単項数が記号の使用を許可されている場合、この手順は不要です。


ループの始まりは最初のファイルと見なされますか?
mbomb007

@ mbomb007はい。私はドキュメントでそれを見ていましたが、マーティンがそれを思い出すまで忘れていました。;)
DLosc

2

さび、170文字

fn f(s:String)->i32{let(mut a,mut b)=(-1,-1);for c in s.chars(){if b!=-1{a=match c{'.'=>a+b,':'=>a*b,_=>0};b=-1}else{b=match c{'.'=>1,':'=>2,_=>0};if a==-1{a=b;b=-1}};}a}

Rustがゴルフで絶対にひどいということのより多くの証拠。完全な未コード:

#[test]
fn it_works() {
    assert_eq!(dotty_ungolfed("::...:.:.".to_string()), 9);
    assert_eq!(f("::...:.:.".to_string()), 9);
}

fn dotty_ungolfed(program: String) -> i32 {
    let (mut a, mut b) = (-1, -1);
    for ch in program.chars() {
        if b != -1 {
            a = match ch { '.' => a + b, ':' => a * b, _ => panic!() };
            b = -1;
        } else {
            b = match ch { '.' => 1, ':' => 2, _ => panic!() };
            if a == -1 { a = b; b = -1; }
        }
    }
    a
}

fn f(s:String)->i32{let(mut a,mut b)=(-1,-1);for c in s.chars(){if b!=-1{a=match c{'.'=>a+b,':'=>a*b,_=>0};b=-1}else{b=match c{'.'=>1,':'=>2,_=>0};if a==-1{a=b;b=-1}};}a}

これは私がこれで使用した興味深いトリックです。すぐに破棄される値を返すようにすることで、if / elseステートメントで文字を削除できます。つまり、2つではなく1つのセミコロンだけが必要です。

例えば、

if foo {
    a = 42;
} else {
    doSomething(b);
}

に変更することができます

if foo {
    a = 42
} else {
    doSomething(b)
};

セミコロンを削って文字を保存します。


2

Haskell、 88 81 79バイト

(h:t)![p,q]|h=='.'=t![p+q]|1<2=t![p*q]
(h:t)!s|h=='.'=t!(1:s)|1<2=t!(2:s)
_!s=s

Haskellのソリューションで誰かが私をbeat打したようです。それだけでなく、彼らのソリューションは私のソリューションよりも短いのです。それは悪いことですが、思いついたことを投稿しない理由はありません。


2

APL(50)

APLはスタックベースの言語ではないため、ここで大きな不利益を被っています。しかし、プログラムを短縮するためにようやく虐待の削減になりました。

{⊃{F←'.:'⍳⍺⋄2>⍴⍵:F,⍵⋄((⍎F⌷'+×')/2↑⍵),2↓⍵}/(⌽⍵),⊂⍬}

内部関数は、左側に「コマンド」、右側にスタックを受け取り、それを適用してスタックを返します。外部関数は、空のスタックから始めて、文字列全体でそれを減らします。

説明:

  • (⌽⍵),⊂⍬:削減する最初のリスト。⊂⍬スタックを表すボックス化された空のリストです。(⌽⍵)は、入力の逆です。(リスト上で右から左に縮小が適用されるため、文字列は右から左に処理されます。事前に入力を逆にすると、文字が正しい順序で適用されます。)

  • {...}:内部関数。右側のスタック、左側の文字を受け取り、変更されたスタックを返します。

    • F←'.:'⍳⍺:文字列内の文字のインデックス .:。これは、値に応じて1または2になります。
    • 2>⍴⍵:F,⍵:2が現在のスタックサイズより大きい場合は、現在の値をスタックに追加します。
    • : さもないと、
      • 2↓⍵:スタックから上位2つのアイテムを削除します
      • (... )/2↑⍵:指定された関数をそれらの上で縮小し、スタックに追加します。
      • ⍎F⌷'+×':関数は+(加算)または×(乗算)であり、で選択されFます。
  • :最後に、スタックの一番上のアイテムを返します


2

ルビー-96文字

ここでのちょっと面白い作品はeval

それとは別に、最初の文字の後、スタックは常に2、数学、2、数学、...になると仮定しています。文字が数学か数字かを判断します。それは定位置です。

x,m=$<.getc>?.?2:1
(b,f=m.split //
b=b>?.?2:1
x=f ?eval("x#{f>?.??*:?+}b"):b)while m=gets(2)
p x

ゴルフをしていない:

bottom_of_stack = $<.getc > '.' ? 2 : 1 # if the first char is ., 1, else 2
two_dots = nil
while two_dots = gets(2) do # get the next 2 chars
  number_char, math_char = two_dots.split //
  number = number_char > '.' ? 2 : 1
  if math_char
    math = math_char > '.' ? '*' : '+'
    # so bottom_of_stack = bottom_of_stack + number ...
    # or bottom_of_stack = bottom_of_stack * number
    bottom_of_stack = eval("bottom_of_stack #{math} number")
  else
    # if there's no math_char, it means that we're done and 
    # number is the top of the stack
    # we're going to print bottom_of_stack, so let's just assign it here
    bottom_of_stack = number
  end
end
p bottom_of_stack  # always a number, so no need for `puts`

2

TI-BASIC、78 73 70 69 66バイト

Input Str1
int(e^(1=inString(Str1,":
For(A,2,length(Str1),2
Ans+sum({Ans-2,1,1,0},inString("::..:",sub(Str1,A,2
End
Ans

閉じ括弧はオプションなので、TI-BASICはワンライナーが得意です。逆に、変数への格納には2〜4バイトのスペースが必要になるため、複数の値を格納する必要がある貧弱な言語です。したがって、目標は各行にできるだけ多く書くことです。TI-BASICは、あらゆる種類の文字列操作においても(トークン化された言語の場合)ひどいです。部分文字列の読み取りでも時間がかかります。

トリックは次のとおりです。

  • int(e^([boolean]代わりに1+(boolean; 1バイト節約
  • リストのスライスではなくリストの部分的な合計(リストに保存する必要があります):3バイトを節約します

".:.":prgmDOTTY4バイトを節約するなど、Ansから入力を取得しても問題ないはずです。
MIライト

@Wright Ansを使用して、スタックに数値を格納します。
リルトシアスト

私は最初に1+(":"=sub(Ans,1,1
-MIライトに

1
Ansが取得されるループでStr1を使用する必要があるため、文字列をAnsに保持することで逃げることができません。AnsからStr1に保存しても、スペースは節約されません。
リルトシアスト

1

行く、 129 115 112バイト

func m(s string){a,b:=0,0;for c,r:=range s{c=int(r/58);if b>0{a=a*b*c+(a+b)*(c^1);b=0}else{b,a=a,c+1}};print(a)}

(やや)改変されていない:

func m(s string){
    // Our "stack"
    a, b := 0, 0
    // abusing the index asignment for declaring c
    for c, r := range s {
        // Ascii : -> 58, we can now use bit fiddeling
        c = int(r / 58)
        if b > 0 {
            // if r is :, c will be 1 allowing a*b to pass through, c xor 1 will be 0
            // if r is ., c xor 1 will be 1 allowing a+b to pass through
            a = a*b*c + (a+b)*(c^1)
            b = 0
        } else {
            b, a = a, c+1 // Since we already know c is 0 or 1
        }
    }
    print(a)
}

ここでオンラインで試してください:http : //play.golang.org/p/B3GZonaG-y


1

Python 3、74

x,*s=[1+(c>'.')for c in input()]
while s:a,b,*s=s;x=[x*a,x+a][-b]
print(x)

最初に、入力リストを1と2のシーケンスに変換し、最初の値を初期値として使用しますx。次に、の前から一度に2つの要素をs取り出し、最初の数値を取得し、2番目が1か2かに基づいて現在の数値を加算または乗算します。


1

まあ、これは非常に簡単な操作で、操作によって洗練されています(意図的に)

それはただ...

後置* / +操作に変換される括弧付きの式

コード:C(80バイト)

int f(char*V){return*(V-1)?f(V-2)*(*V==58?*(V-1)/29:1)+(*V&4)/4**(V-1)/29:*V/29;}
  • この関数は、次のような文字列の末尾から呼び出す必要があります。f(V + 10)where V = "。:..:。:.. ::"

入力

length = 2n + 1型char '。'のベクトルV または「:」

出力

整数k

関数

  • k =(V [1] op(V [3])V [2])op(V [5])V [4] ....

  • op(x):(x = '。')-> +、(x = ':')-> *


シミュレーション:

ここで試してください


文字列(*(V-1))の前のバイトがゼロであるとどのように仮定できますか?
-nutki

新しいベクトルを割り当てる際に、その始まりはいつもそれは、空のセグメントからその終わりを開始IS空の文字
Abr001am

1

網膜、181の 135 129バイト

各行は個別のファイルにある必要があります。<empty>空のファイルを表します。出力は単項です。

^\..*
$&1;
^:.*
$&11;
^.
<empty>
(`^\..*
$&1
^:.*
$&11
^.(.*?1+;1+)
$1
^(\..*);(1+)
$1$2;
;1$
;
^(:.*?)(1+).*
$1$2$2;
)`^.(.*?1+;)
$1
;
<empty>

いつ ${0}1使用されるブレースを分離、$0から1、そうでない場合は次のようになり$01、第1の整合グループ。を使用してみました$001が、これは.NETの正規表現では機能しないようです。

編集:$&と同じであることがわかりました$0

擬似コードでは、以下に示すように、これは本質的にdo-whileループになります。最初の数値をプッシュしてからループします。2番目の数値をプッシュし、操作(命令)を削除し、数学を行い、opを削除します。ループを続けます。操作がポップされると、すべての指示が完了した後にスペースも削除されることに注意してください。

コメント:

^\..*           # Push if .
$&1;
^:.*            # Push if :
$&11;
^.              # Pop op
<empty>


(`^\..*         # Loop, Push #
$&1
^:.*
$&11
^.(.*?1+;1+)    # Pop op
$1


^(\..*);(1+)    # Add if . (move ;)
$1$2;
;1$          # If mul by 1, remove
;
^(:.*?)(1+).*   # Mul if : (double)
$1$2$2;
)`^.(.*?1+;)    # Pop op, End Loop (clean up)
$1
;               # Remove semicolon
<empty>

私はゴルフワイズ見ている主なものは、パターン/置換の組のようです(:)(.*)> - $1$2私はかなり確信しているだけかもしれない(:.*)> - $1あなたが同じ順序で2つのグループを維持し、彼らと何かをしないので、( )。
DLosc

私はインスピレーションを得て、自分のRetinaの答えを作りました。この興味深い言語をダウンロードしてくれてありがとう!
DLosc

@DLoscクール!ええ、実際にはダウンロードしていません。私は、個々の交換ごとにオンライン正規表現交換テスターを使用しました。
mbomb007

0

Python 3、122バイト

x=input()
l=[0,0]
for _ in x:
 t=len(l)-2<2
 l=[[[0,0,l[-2]*l[-1]],l+[2]][t],[[0,0,sum(l)],l+[1]][t]][_=='.']
print(l[-1])

ゴルフをしていない:

x = input()
l = []
for i in x:
    if i == '.':
        if len(l) < 2: 
            l+=[1]        #True, True = 1,1
        else:
            l=[sum(l)]    #True, True = 1,0
    else:
        if len(l)<2:
            l+=[2]        #False, True = 0,1
        else:
            l=[l[0]*l[1]] #False, False = 0,0
print (l[0])

Pythonでは、次のようにリストのインデックスを参照します。

list[index]

ブール値をTrueis 、is 1およびFalseisに入れることができ0ます。

# t is True if the length is less than 2, else false.

l=[ 

  # |------- Runs if char is : -------|
  # |------- l<2 -------| |- l>=2 -|

    [ [ 0,0, l[-2]*l[-1] ], l+[2] ] [t],

                                      # |---- Runs if char is . ----| 
                                      # |--- l<2 ---|  |- l>=2 -|

                                        [ [0,0, sum(l)], l+[1] ] [t] ]
                                                                      [_=='.']

こちらからオンラインでお試しください


0

Perl、77バイト

@o=(0,'+','*');sub d{$_=shift;y/.:/12/;eval'('x s!\B(.)(.)!"$o[$2]$1)"!ge.$_}

展開された:

@o=(0, '+', '*');
sub d{
    $_=shift;
    y/.:/12/;
    eval '(' x s!\B(.)(.)!"$o[$2]$1)"!ge.$_
}

@o配列は、オペレータに数字をマッピングします。次に、数字のペアを適切な演算子で置き換え、中置に並べ替えます。正規表現はで始まる\Bため、最初の文字とは一致しません。の結果はs///g、最初に必要なオープンペアレンの数を示しています。その後、完全な中置式を組み立てたら、それを評価できます。(削除eval代わりに式を見たい場合はしてください)。

結果を検証するために使用したテストハーネスは次のとおりです。

while(<>) {
    my ($a, $b) = m/(.*) (.*)/;
    print d($a), " $b\n";
}

入力はdotty式とその値(質問で提供)のリストであり、出力は{actual、expected}のペアです。

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