Brainf * ckish方向


14

あなたのタスク-あなたがそれを受け入れることを選択した場合-は、方向を与えるトークンの文字列(左から右、任意の長さ)を解析および評価するプログラムを構築することです-左または右。4つの可能なトークンとその意味は次のとおりです。

>  go right one single step
<  go left one single step
-> go right the total amount of single steps that you've gone right, plus one,
   before you previously encountered this token and reset this counter to zero
<- go left the total amount of single steps that you've gone left, plus one,
   before you previously encountered this token and reset this counter to zero

ただし、キャッチがあります。プログラムが解析できるはずの方向のトークンは、次の形式で表示されます。

<<->-><<->->>->>->

...言い換えると、それらは連結されており、指示の正しい優先順位と実行するステップの量を(先読みすることによって)把握することはプログラムのタスクです。優先順位は次のとおりです(最高の優先順位から最低の優先順位へ)。

  1. ->
  2. <-
  3. >
  4. <

あなたが発生した場合は<-、左へのステップは、以前のいずれかの開始以降または最後のリセット以降に行われていなかったとき、左に1つのステップを取ります。同じルールがに適用されますが->、その後は右に移動します。

プログラムは0から始まり、その結果は最終的な終了位置を表す符号付き整数でなければなりません。

入力が常に有効であると期待される場合があります(<--->>--<たとえば、のようなものはありません)。

入力例:

><->><-<-><-<>>->

この例の手順:

 step | token | amount | end position
------+-------+--------+--------------
   1. |   >   |     +1 |           1  
   2. |   <   |     -1 |           0  
   3. |  ->   |     +2 |           2  
   4. |   >   |     +1 |           3  
   5. |   <-  |     -2 |           1  
   6. |   <   |     -1 |           0  
   7. |  ->   |     +2 |           2  
   8. |   <-  |     -2 |           0  
   9. |   <   |     -1 |          -1  
  10. |   >   |     +1 |           0  
  11. |   >   |     +1 |           1  
  12. |  ->   |     +3 |           4  

明確化のために:プログラムの出力は、符号付き整数としての最終終了位置のみであるべきです。上記の表は、私の例が実行した手順を示すためのものです。このようなテーブル、テーブル行、またはステップの終了位置だけを出力する必要はありません。符号付き整数としての最終終了位置のみが必要です。

1週間後の最短コードが勝ちます。


4
優先順位規則を正しく理解している場合、呼び出すことができるの<-は、直後にa <またはaが続く場合だけです->。この言語では、<-当時のシーケンスを表す方法はありませ>go left the total amount of single steps that you've gone left, plus one, then go right one single step。これは正しいですか、設計上ですか?
アダムデイビス14

@AdamDavisそのとおりです。残念ながら、それは私には少し不注意でした。
まともなダブラー14

回答:


6

GolfScript、46文字

'->'/')'*.'<-'-.')'/);+,\'>)'-.'<-'/);\'-'-+,-

これは、私がこれまで書いた中で最も線形のGolfScriptプログラムの1つです。単一のループ、条件、変数の割り当てはありません。すべては文字列操作を使用して行われます。

  • まず、私のすべての出現置き換える->ことによってを)。入力が有効であることが保証されているため、これにより、の残り-がの一部である必要があります<-

  • 次に、文字列のコピーを2つ作成します。最初のコピーから、文字<とを削除し、と-のみ>を残し)ます。次に、結果を複製し、2番目のコピーからすべての)sと>最後のすべてを削除し、)それらを連結して文字をカウントします。したがって、実際には、私はカウントしています:

    • 各+1 )
    • >最後の後にそれぞれに対して+1 )、および
    • >最後の前のそれぞれに対して+2 )
  • 次に、私はこの時間のカウントを除いて、他のコピーの同じやる<<-代わりの>)、削除-、最終的な文字カウントの前にSを。したがって、私は数えます:

    • 各+1 <-
    • <最後の後にそれぞれに対して+1 <-、および
    • <最後の前のそれぞれに対して+2 <-
  • 最後に、最初のカウントから2番目のカウントを減算し、結果を出力します。


6

Pythonの2.7 - 154 147 134 128バイト

l=r=p=0
exec"exec raw_input('%s->','p+=r+1;r=0%s<-','p-=l+1;l=0%s>','r+=1;p+=1%s<','l+=1;p-=1;')"%((";').replace('",)*4)
print p

このプログラムの動作方法に重大な変更が加えられました。古い説明は削除しましたが、この回答の編集履歴にまだあります。

これはひどい。

この質問に対する他の回答とほとんど同じように機能し、入力の文字をその言語の有効なステートメントに置き換えて実行します。ただし、大きな違いが1つあります。replaceます。長い言葉です。それをねじ込みます。

チャットの@ProgrammerDanは、文字列;').replace('を4回含むタプルを使用して、str.format()テキストをフォーマットする事前メソッドを使用するというアイデアを思いつきました。の4つのインスタンスは%s、2行目の文字列にあり、各インスタンスは、最後のタプルの関連要素から値を取得します。それらはすべて同じであるため、それぞれ%sがに置き換えられ;').replace('ます。操作を実行すると、次の文字列が取得されます。

exec raw_input(';').replace('->','p+=r+1;r=0;').replace('<-','p-=l+1;l=0;').replace('>','r+=1;p+=1;').replace('<','l+=1;p-=1;')

これは、で実行できる有効なpythonコードですexec。そうです、ベイビー:ネストされたexecsは、コードで文字列操作を実行する必要があるコードで文字列操作を使用できます。誰かが私を殺してください。

残りは非常に簡単です。各コマンドは、現在の位置、最後からの権利の数->、およびleftsとの同じ3つの変数を追跡するコードに置き換えられます<-。全体が実行され、位置が印刷されます。

raw_input(';')「;」を使用して、私が行うことに気付くでしょう プロンプトraw_input()がないのではなく、プロンプトとして。これは直感的ではない方法で文字を保存します:私がした場合raw_input()、タプルをで満たす必要が).replace('あり、のすべてのインスタンス%sは '; \' 'の前に最初のものを除きます。プロンプトがあると冗長性が増えるため、全体的に多くのキャラクターを保存できます。


2
「キャラクターが見つからなかった場合にlist.index()戻ります-1」.. erm no。を発生させIndexErrorます。あなたはそれと混同しているかもしれませんstr.find。実際には、あなたは置き換えることができ[list('><rl').index(c)]['><rl'.find(c)]
バクリウ14

...ハァッ、私はドキュメントでそれを調べ、-1を返したと誓ったかもしれません。それは特にリストのページだったので、何を読んだのか分かりません。とにかく、助けてくれてありがとう、答えにそれを編集します。
地下

5

Perl、134 131 ... 99 95バイト

sub f{$p+=$d;$&=~/-/?($p+=$s,$s=0):($s+=$d)}$_=<>;$d=1;s/-?>/f/eg;$s=0;$d=-1;s/<-?/f/eg;print$p

入力を標準入力の単一行として取得します。例:

ski@anito:~$ perl -le 'sub f{$p+=$d;$&=~/-/?($p+=$s,$s=0):($s+=$d)}$_=<>;$d=1;s/-?>/f/eg;$s=0;$d=-1;s/<-?/f/eg;print$p'
><->><-<-><-<>>->
4

または:

ski@anito:~$ echo "><->><-<-><-<>>->" | perl -le 'sub f{$p+=$d;$&=~/-/?($p+=$s,$s=0):($s+=$d)}$_=<>;$d=1;s/-?>/f/eg;$s=0;$d=-1;s/<-?/f/eg;print$p'
4

命令を「右」演算子(「>」および「->」)と「左」演算子(「<」および「<-」)に分割します。これの利点は、左演算子と右演算子の間の並列性を活用するのが簡単であり、文字列をトークン化するのに何もする必要がないことです。各「方向」は、他の置換操作で処理される逆方向を無視して、その方向で実行されるステップの数で実行合計を調整する置換操作として扱われます。一種のドキュメントとしての、このコードのあまりゴルフをしていない祖先は次のとおりです。

sub f {
  $dir=shift;
  if($1 =~ /-/) {
    $pos+=$side+$dir;
    $side=0;
  } else {
    $pos+=$dir;
    $side+=$dir;
  }
}

$_=<>;

s/(-?>)/f(1)/eg;
$side=0;
s/(<-?)/f(-1)/eg;

print $pos

このコードの以前の反復では、置換はすべて1つのパスで行われました。これには、$ p / $ posと特定の時点で返される位置との間の直接マッピングを保持するという利点がありましたが、より多くのバイトのコードが必要でした。

use()5.10.0を使用する場合は、s / print / say /を使用して、カウントからさらに2文字を削ることができますが、それは実際には私のスタイルではありません。


4

Perl、88 77バイト

$_=<>;print s/->/F/g+2*s/>(?=.*F)//g+s/>//g-(s/<-/B/g+2*s/<(?=.*B)//g+s/<//g)

STDINを介した入力が期待されます。例:

echo '><->><-<-><-<>>->'|perl -e '$_=<>;print s/->/F/g+2*s/>(?=.*F)//g+s/>//g-(s/<-/B/g+2*s/<(?=.*B)//g+s/<//g)'
4

更新

s//すでにカウントしているため、文字列を合計に変換する必要はありません。:-)

最初のバージョン

$_=<>;s/->/+1/g;s/>(?=.*1)/+2/g;s/>/+1/g;s/<-/-1/g;s/<(?=.*-)/-2/g;s/</-1/g;print eval

STDINを介した入力が必要です。例:

echo '><->><-<-><-<>>->'|perl -e '$_=<>;s/->/+1/g;s/>(?=.*1)/+2/g;s/>/+1/g;s/<-/-1/g;s/<(?=.*-)/-2/g;s/</-1/g;print eval'
4

説明:

アイデアは、結果が単純なによって出力されるように、方向文字列を合計に変換することですprint eval

>いずれかの前に->二つのステップ、一度に1つずつと、次の他のを取ります->。それは重要ではありませんが、そのうちの->少なくとも1つに続いている間です。内部カウンタは次の後にリセットされるため->>それ以上のステップは発生しません。最大は2ステップです。次に->、自分自身に1つのステップを追加し>、最後の残りのステップを追加します->

同じことは、正のステップ数ではなく負のステップ数で逆方向にも当てはまります。

例えば: ><->><-<-><-<>>->

s/->/+1/->優先順位が最も高いため、順方向から始めます。
例えば:><+1><-<+1<-<>>+1

s/>(?=.*1)/+2/g:先読みパターンは、>前のもののみ->が変換されることを保証します。
例えば:+2<+1+2<-<+1<-<+2+2+1

s/>/+1/g:残り>はカバーされています。
例えば:+2<+1+2<-<+1<-<+2+2+1

s/<-/-1/g:逆方向にアナログ。
例えば:+2<+1+2-1<+1-1<+2+2+1

s/<(?=.*-)/-2/g:先読みパターンで-1は、前者を完全に使用する<-必要はありません-。これは、方向記号が残っていないためです。
例えば:+2-2+1+2-1-2+1-1<+2+2+1

s/</-1/g<最後の残りの<-部分が変換されます。
例えば:+2-2+1+2-1-2+1-1-1+2+2+1

print eval:結果を計算して出力します。
例えば:4


良いもの。私は昨夜この概念を蹴っていましたが、今日までそれを実装しようとする機会がありませんでした。良いことは、投稿を確認し、あなたがすでに持っていた=)
skibrianski 14

@skibrianski:copy&pasteエラーを修正してくれてありがとう。
ヘイコオベルディク14

もう少しゴルフをすることができます:65バイト または、使用せずに-p74バイト各ケースでバイトを保存するs/>//gよう に変更しy/>//ました。
Xcali

2

Ruby、141バイト

l=1;r=1;o=0
gets.gsub('->',?R).gsub('<-',?L).chars{|c|case c
when'<';o-=1;l+=1
when'>';o+=1;r+=1
when'L';o-=l;l=1
when'R';o+=r;r=1
end}
$><<o

ゴルフをしていない:

parsed = gets.gsub('->', 'R')
             .gsub('<-', 'L')
countL = 1
countR = 1
result = 0
parsed.each_char do |c|
    case c
    when '<'
        result -= 1
        countL += 1
    when '>'
        result += 1
        countR += 1
    when 'L'
        result -= countL
        countL = 1
    when 'R'
        result += countR
        countR = 1
    end
end
puts result

いくつかの素早い勝ち:ありl=1;r=1得ることもl=r=1あり$><<o得ることもありますp o。私はあなたが何かかさばら、の線に沿って多分何かで、その場合ステートメントを置き換えることにより、多くのことを剃ることができると思うeval %w(o-=1;l+=1 o+=1;r+=1 o-=l;l=1 o+=r;r=1)['<>LR'.index c]
ポールPrestidge

実際、evalアプローチでは、いくつかのプレフィックス/サフィックスを引き出して、さらに節約できます。これは98文字です:l=r=1;o=0;gets.gsub('->',??).scan(/<-|./){eval"o+=#{%w[-1;l+ -l;l 1;r+ r;r][$&[-1].ord%4]}=1"};p oを使用して94に下げることができますruby -p
ポールPrestidge 14

1

D-243

Golfed

import std.regex,std.stdio;void main(string[]a){int s,c,v;auto t=a[1].matchAll("->|<-(?!>)|>|<".regex);foreach(m;t){auto r=m.hit;if(r=="->"){s+=c+1;c=0;}else if(r=="<-"){s-=v+1;v=0;}else if(r==">"){++s;++c;}else if(r=="<"){--s;++v;}}s.write;}}

ゴルフをしていない

import std.regex, std.stdio;

void main( string[] a )
{
    int s, c, v;
    auto t = a[1].matchAll( "->|<-(?!>)|>|<".regex );

    foreach( m; t )
    {
        auto r = m.hit;

        if( r == "->" )
        {
            s += c + 1;
            c = 0;
        }
        else if( r == "<-" )
        {
            s -= v + 1;
            v = 0;
        }
        else if( r == ">" )
        {
            ++s;
            ++c;
        }
        else if( r == "<" )
        {
            --s;
            ++v;
        }
    }

    s.write;
}

必要な出力はもともと質問にありました。私は今それを強調し、さらに明確化を追加しました。
まともなダブラー14

答えを編集して結果を出力しました。
トニーエリス14

1

C、148 141 140

140:

r,l,o;main(char *x,char **v){for(x=v[1];*x;x++)(*x^45)?(*x^60)?(r++,o++):(*(x+1)==45)?(x++,o-=l+2,l=0):(o--,l++):(o+=r+1,r=0,x++);return o;}

141:

r,l,o;main(char *x,char **v){for(x=v[1];*x;x++)(*x^45)?(*x^60)?(r++,o++):(*(x+1)==45)?(x++,o=o-l-2,l=0):(o--,l++):(o+=r+1,r=0,x++);return o;}

148:

r,l,o;main(char *x,char **v){for(x=v[1];*x;x++){if(*x^45){if(*x^60)r++,o++;else{o--,l++;if(*(x+1)==45)x++,o-=l,l=0;}}else o+=r+1,r=0,x++;}return o;}

空白あり:

r,l,o;
main(char *x,char **v) 
{
    for(x=v[1];*x;x++)
    (*x^45) ?
        (*x^60) ?
            (r++,o++)
            :
            (*(x+1)==45) ?
                (x++,o-=l+2,l=0)
            :(o--,l++)
        :(o+=r+1,r=0,x++);
    return o;
}

おそらくこれをゴルフするためのより多くの部屋。私はほとんど、左辺値を捕らえた3つの変数の4つの変数を操作しようとすることをあきらめました(それはより長く出て、後で取得しました)が、悪い最初のパスではありません。かなり単純な配列パス。入力をコマンドライン引数として受け取り、戻り値を介して出力します。

-std=c99gccでコンパイルするにはフラグが必要です。

編集: うん、それは遅い-いくつかの明らかなものを見逃した。


次の引数リストから2つのスペースを削除できますmainmain(char*x,char**v)。そして、あなたは138の代わりに140を持っている
ハイコOberdiek

バグがあります:>><-0ではなく1を与えるか、><->2の代わりに0を与える
ハイコOberdiek

間のあなたの削除スペース場合は、4つのバイトを保存することができますchar*、とは交換してください(*(x+1)==45)?(x++,o-=l+2,l=0):(o--,l++)(*++x==45)?(o-=l+2,l=0):(x--,o--,l++)
マチューロディック14

1

JavaScript、136

z=0;l=r=1;c=["--z;++l;",/</g,"++z;++r;",/>/g,"z-=l;l=1;",/<-/g,"z+=r;r=1;",/->/g];for(a=8;a--;s=s.replace(c[a--],c[a]));eval(s);alert(z)

未縮小:

s="><->><-<-><-<>>->";
z=0;
l=r=1;
c=[
    "--z;++l;", /</g,
    "++z;++r;", />/g,
    "z-=l;l=1;", /<-/g,
    "z+=r;r=1;", /->/g
];
for(a=8;a--;s=s.replace(c[a--],c[a]));
eval(s);
alert(z) // Output (4)

使い方

文字列入力として sような:

s="><->><-<-><-<>>->";

正規表現を使用して、各コマンドを変更する一連の指示に置き換えます z(終了位置)、l(保存された左の動き)、およびr保存された右の動き。各正規表現は優先順に実行されます。

上記の入力の場合、これは次のように変換さsれます。

"++z;++r;--z;++l;z+=r;r=1;++z;++r;z-=l;l=1;--z;++l;z+=r;r=1;z-=l;l=1;--z;++l;++z;++r;++z;++r;z+=r;r=1;"

かなり、そうではありません。

最後に、終了位置を含むeval(s)指示と警告を実行しますz


1

ジャバスクリプト(116、122130

116:

for(l=r=p=i=0;c='<>-0'.indexOf(a.replace(/->/g,0)[i++])+1;p--)c-4?c-3?c-2?l++:(r++,p+=2):(p-=l-2,l=0):(p+=r+2,r=0);p

122:

for(l=r=p=i=0,a=a.replace(/->/g,0);c='<>-0'.indexOf(a[i])+1;i++,p--)c-4?c-3?c-2?l++:(r++,p+=2):(p-=l-2,l=0):(p+=r+2,r=0);p

130:

for(l=r=p=i=0;c='<>-'.indexOf(a[i])+1;i++,p--)c-3?c-1?(r++,p+=2):a[i+1]=='-'?a[i+2]=='>'?l++:(p-=l,l=0,i++):l++:(p+=r+2,r=0,i++);p

0

JavaScript [217バイト]

prompt(x=l=r=0,z='replace',f='$1 $2 ')[z](/(>.*?)(->)/g,f)[z](/(<.*?)(<-)/g,f)[z](/(<|>)(<|>)/g,f)[z](/<-?|-?>/g,function(c){c=='>'&&(x++,r++),c=='<'&&(x--,l++),c=='->'&&(x+=++r,r*=0),c=='<-'&&(x-=++l,l*=0)}),alert(x)

おそらくもう少し短くなるかもしれません...


0

PHP、284 282

正規表現なし。

$i=fgets(STDIN);$c=$a=0;$s=str_split($i);while($c<count($s)){switch($s[$c]){case"<":if($s[$c+1]=="-"){if($s[$c+2]==">"){$c+=3;$a+=$rr;$rr=0;$ll++;}else{$c+=2;$a+=-($ll+1);$ll=0;}}else{$c++;$a--;$ll++;}break;case">":$c++;$a++;$rr++;break;case"-":$c+=2;$a+=$rr+1;$rr=0;break;}}echo$a;

ゴルフをしていない:

$i=fgets(STDIN);
$c=$a=0;
$s=str_split($i);
while($c<count($s)){
    switch($s[$c]){
    case "<":
        if($s[$c+1]=="-"){
            if($s[$c+2]==">"){
                $c+=3;$a+=$rr;$rr=0;$ll++;
            }
            else{
                $c+=2;$a+=-($ll+1);$ll=0;
            }
        }
        else{
            $c++;$a--;$ll++;
        }
    break;
    case ">":
        $c++;$a++;$rr++;
        break;
    case "-":
        $c+=2;$a+=$rr+1;$rr=0;
        break;
    }
}
echo $a;

str_split($i)12番目の引数のデフォルトは)で2文字獲得できます。そして、$iおそらく$c正しいはずです。
まともなダブラー14

最初の行が間違っていた(それは$i):P修正済み!
ヴェレオ14

0

別のperlソリューション、113文字

これを打つ2つの答えがすでにあります、それは笑いのためだけです。トークンの値に関するIlmariの観察に基づくアプローチを使用します。

$_=<>;chomp;s/->/#/g;s/<-/%/g;s/>(?=.*#)/?/g;s/<(?=.*%)/;/g;s/#/>/g;s/%/</g;$t+=ord for split//;print$t-61*length

少し爆発した:

$_=<>;
chomp;
s/->/#/g;
s/<-/%/g;
s/>(?=.*#)/?/g;
s/<(?=.*%)/;/g;
s/#/>/g;
s/%/</g;
$t+=ord for split//;
print$t-61*length
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.