丘を転がる岩を計算する


15

前書き

Sisyphusは最近仕事でいくつかの問題を抱えていました。彼は何も成し遂げられなかったようで、この問題の解決策を見つけたいと思っています。

彼の現在の雇用には、岩を丘の上に転がすことが必要です。彼は通常、仕事をうまくこなしますが、彼が丘の頂上に近づくたびに、それは再び転がり落ちます。

彼は自分の仕事に本当に不満を感じており、丘を転がる岩をコンピューターにシミュレートさせることにより、科学的に問題を解決したいと考えています。

Sisyphusはプログラミングが特に得意ではないので、手伝ってもらえますか?

チャレンジ

この愚かな紹介の後、ビジネスに取り掛かりましょう。あなたのプログラムは、これに似た丘と岩のイラストを受け取ります:

#o        
##
###
######
######## 

どこ#が丘の一部をo表し、岩を表します。

次に、岩1のレイヤーを下に移動するプログラムを実装する必要があります。たとえば、上記の出力は次のようになります。

#        
##o
###
######
######## 

水平方向に均等なエリアがある場合、丘は水平方向に転がるだけなので、...

o
######## 

...これにより、石が横に転がります。

 o
######## 

垂直方向の領域がある場合、岩は1ステップ下に落ちるので、...

#o
#
#
##### 

...得られます...

#
#o
#
##### 

また、画像の幅と高さをそれぞれ画像の上の1行で受け取ります。したがって、サンプル入力は次のようになります。

10 5
#o        
##        
###       
######    
######### 

(ここでの空白はスペースです。テキストを選択して、意味を確認してください。)

いくつかの詳細

  • プログラムの実行時に岩がすでに最後の行にある場合、プログラムを終了するか、変更されていない入力を出力するかを選択できます。
  • 丘は下に行くだけです
  • プログラムは、出力(入力を含む)とまったく同じように出力をフォーマットする必要があるため、プログラムの出力をそれ自体にパイプすると、次のステップが計算されます。

  • 常に最下部への道があると想定できるため、パスが「ブロック」されている入力は未定義の動作を引き起こす場合があります

  • 最後の行に常にスペースがあると仮定できます。岩はそこに「休む」必要があるため、プログラムを数回呼び出して、常に出力をそれ自体にパイプすると、最後の行に岩があり、以前はスペースがあった場所に配置する必要があります。

  • 任意の形式(stdin、file、...)で入力を受け入れることができます。WHOLEプログラムをポストする必要があります(したがって、すべての事前初期化された変数はコードとしてカウントされます)。

  • 行はで終了し\nます。

  • ここでいくつかのサンプル入力を取得できます(スペースを正しくコピーしてください!)

  • これはなので、バイト数が最小の作業中のサブミッションが勝ちます。

  • 勝者は2014年7月26日に選ばれます。その後、解決策を投稿できますが、勝つことはできません

ご質問がある場合は、コメントでお知らせください。

ハッピーゴルフ!


最後の例のように空白の末尾の列がありますか?(他の人が持っていないため)
マーティンエンダー

@ m.buettner最後の例では9 #秒しかありません。したがって、幅が10であるため、最後に1つのスペースがあります。 -右隅)。
クリストフベームヴァルダー14

はい、私は気づいています、私はそれが常にそうであると仮定できるかどうか疑問に思っていました、なぜならそれはあなたの他の例のためではないからです。(とはいえ、他の例には末尾の空白はまったくありません。)
マーティンエンダー14

6
「ロックンロール」と呼ぶ絶好のチャンスを逃した
qwr 14

1
@HackerCowあなたは正しい。キャラクターを削除することで修正:D
マーティンエンダー14

回答:


33

正規表現(.NET、Perl、PCRE、JavaScript、...フレーバー)、25バイト

はい、これは正規表現が有効なプログラムであるかどうかにかかわらず、いくつかの議論を引き起こしますが、私はそれを先取りし、この提出は単なる楽しみのためであり、勝者のために考慮する必要はないと言います。(下部の31バイトPerlバリアントとは対照的に;)。)

したがって、ここに純粋な正規表現置換ソリューションがあります。

パターン(末尾のスペースに注意してください):

o(( *)\n#*)(?=\2) |o 

置換(先頭のスペースに注意してください):

 $1o

バイトカウントは、2つの合計です。

http://regexhero.net/tester/でテストできます。貼り付けるときは、Unixスタイルの行末を選択し、「貼り付けた書式を保持する」ようにしてください。それでも機能しない場合は、Windowsスタイルの行末を貼り付けています。その場合の最も簡単な修正方法は、パターン内でを置き換え\n\r\n、機能することを確認することです。

これを使用した48バイトの ECMAScript 6関数を次に示します。

f=(s)=>s.replace(/o(( *)\n#*)(?=\2) |o /,' $1o')

最後に、実際のプログラムもあります。Perl の31バイトです(for p0flagsの2バイトを含みます。提案についてはVenteroに感謝します!)。

s/o(( *)\n#*)(?=\2) |o / $1o/

テストする場合は、ファイルに保存しないでください。

perl -p0e 's/o(( *)\n#*)(?=\2) |o / $1o/' < hill.txt

残念ながら(オンラインテスターでは)動作しません。常に岩を右に移動します。しかし、40バイトは素晴らしいスタートです。
クリストフベームヴァルダー14

@HackerCowそうですね、問題があることに気づきました。...修正
マーティン・エンダー

@HackerCowいいえ、実際に動作すると思いますが、「フォーマットを保持する」は行末を上書きするため、Windowsスタイルの行末を貼り付けると機能しません(置き換え\nてみてください\r\n
Martin Ender 14

私にとって、岩は右の壁にぶつかっても落ちません。末尾にスペースがある場合にのみ一致します。
BrunoJ

4
これをどうやって倒すのですか?グレートソリューション
QWR

3

パイソン-190

スライスと連結の恐怖と、あまりにも多くの変数。これはもっとゴルフができると確信していますが、今のところ巧妙なpython関数は考えられません。入力はstringに保存されますs

r=" "
o="o"
i=s.index(o)
b=i+int(s.split(r)[1])
q=s[:i]+r
x=s[b+3:]
try:
 a=s[b+1:b+3]
 if a[0]==r:s=q+s[i+1:b+1]+o+r+x
 elif a[1]==r:s=q+s[i+1:b+2]+o+x
 else:s=q+o+s[i+2:]
except:1
print(s)

Python文字列は不変なので、前のすべての文字、新しい文字、および後のすべての文字を連結して文字を置き換えます。丘の幅とインデックスを使用して、岩が転がる場所を決定します。



2

ルビー、65/55文字

解決策がどれだけ長く、問題に正規表現を投げるだけではないかがわかると思いました。

r=gets p
r[r[(r[k=1+~/o/+x=r.to_i,2]=~/ /||-x)+k]&&=?o]=" "
$><<r

予想どおり、m.buettnerの正規表現ソリューションほど短くはありませんが、それほど長くはありません。

インタープリターフラグを使用する場合、これは55文字(コードの場合は53、フラグの場合は2)に短縮できます。

sub$_[($_[k=1+~/o/+x=$_.to_i,2]=~/ /||-x)+k]&&=?o," "

次のようなコードを実行します。

ruby -p0e 'sub$_[($_[k=1+~/o/+x=$_.to_i,2]=~/ /||-x)+k]&&=?o," "' < input

2

HTML JavaScript-251文字

251入力を読み取り、出力を返す単一引用符内のコードをカウントする場合。359入力ボックス、入力文字列、ボタンなどをカウントする場合。192、あなたが仕事をすることだけで数える場合。)

ゴルフコード:

<pre id="i">10 5
#o        
##        
##        
######    
######### </pre><button onclick='i=document.getElementById("i");h=i.innerHTML;if(p=h.
match(/([\s\S]*?)([# ]+)(o *\n)(#+)([\s\S]*)/)){if(p[4].length>p[2].length+1)p[3]=p[3].
replace("o "," o");else{p[3]=p[3].replace("o"," ");p[5]="o"+p[5].substr(1);}p[0]="";
h=p.join("");}i.innerHTML=h;'>Go</button>

http://goo.gl/R8nOIK
「Go」をクリックします
[Go]を繰り返しクリックします。

方法

String.match()を使用してhillを5つの部分に分割し、1つまたは2つの部分を変更します。私はJavaScriptを学んでいるので、どんな提案でも歓迎します。

読み取り可能なコード

<pre id="io">10 5
#o        
##        
##        
######    
######### </pre>

<button onclick='

    // get image
    io = document.getElementById("io");
    image = io.innerHTML;

    // break image into five parts
    // 1(10 5\n#         \n##        \n) 2(### ) 3(o     \n) 4(######) 5(    \n######### )
    if (parts = image.match(/([\s\S]*?)([# ]+)(o *\n)(#+)([\s\S]*)/)) {

        // move rock to the right
        if (parts[4].length > parts[2].length + 1)
            parts[3] = parts[3].replace("o ", " o");

        // or move rock down
        else {
            parts[3] = parts[3].replace("o", " ");
            parts[5] = "o" + parts[5].substr(1);
        }

        // return new image
        parts[0] = "";
        image = parts.join("");

        // MAP io:i image:h parts:p
    }
    io.innerHTML = image;
'>Go</button>

1

Python 2- 289 252バイト

p=raw_input
w,h=map(int,p().split())
m=[p()for a in[0]*h]
j=''.join
f=lambda s:s.replace('o ',' o')
for i,r in enumerate(m):
 x=r.find('o')
 if x+1:y=i;break
if m[y+1][x]=='#':m=map(f,m);x+=1
print w,h
print'\n'.join(map(j,zip(*map(f,map(j,zip(*m))))))

私はいくつかの重要な改善を行いましたが、これはまだひどいです。これをPython 3に変換することでさらに2バイト節約できますが、私は悩まされません。

まず、岩を見つけます。すぐ下の文字がある場合は'#'、のすべてのインスタンス置き換える'o 'とします' o'。最後に余分なスペースがあることが保証されているため、これにより常に岩が右に移動します。

それをやったかどうかに関係なく、グリッド全体をで置き換えzip(*m)ます。その後、私は別の交換を行う'o 'とし' o'。岩の右側にスペースがある場合、実際のグリッドにはその下にスペースがあるため、移動します。次に、転置して印刷します。


これは、岩の右と下に空のスペースがあるOPの3番目の例を台無しにして、斜めに動かさないでしょうか?
ドアノブ

@dorしてはいけません。下のスペースがの場合にのみ右に移動し、#縦に移動するチェックを行う前にそのチェックを行います。
地下

1

パイソン(201)

import sys
print(input())
g=list(sys.stdin.read())
o='o'
x=g.index(o)
n=x+g.index('\n')+1
try:
 if g[n]==' ':g[n]=o
 elif g[n+1]==' ':g[n+1]=o
 else:g[x+1]=o
 g[x]=' '
except:1
print(*g,sep='',end='')

1

awk、152

awk 'NR==1{w=$2}{if(NR<=w&&$0~/o/){r=index($0,"o");g=$0;getline;if(index($0,"# ")<=r){sub("o"," ",g);sub(" ","o")}else{sub("o "," o",g)}print g}print}'

より読みやすい

    awk '
  NR==1{  //If we're at the first line, set the width from the second column in the header.
    width=$2
  }
  {
    if(NR<=width && $0~/o/){   //If not at the bottom, look for the line with the rock.
      rockIndex=index($0,"o"); //Set the position of the rock.
      orig=$0;                 //Remember the current line so we can compare it to the next.
      getline;                 //Get the next line.

      if(index($0,"# ")<= rockIndex){  //Move down: if the rock is on a cliff or on a slope,
        sub("o"," ",orig);             //update the orig so that the rock is removed
        sub(" ", "o")                  //and update the current (first available position).
      }                                         
      else {                           //Move right: if the rock is on flat ground,
        sub("o "," o", orig)           //update the orig so the the rock is advanced.
      }
      print orig                       //Print the line we skipped (but stored      
    }                                  //and updated based on the line we're now on).
    print                              //Print the line we're now on.
  }
'

0

php 485 484文字

これはm.buettnerによるエントリーに比べて膨大ですが、今のところできることは最高です。入力文字列を多次元配列に変換するより迅速な方法が必要だと思いますが、今はとても遅いです。

競争力はありませんが、このパズルが好きでした。拡張機能は、ボールがどこに到達するか、または設定されたステップ数の後、おそらく入力行の幅と高さの後に追加されることを示したいです。このバージョンに非常に簡単に追加できます。

コードは次のとおりです。入力は最初の変数にあります。

<?
$a.='10 5
#o         
##       
###       
######    
#########';$b=array();$c=explode("\n",$a);$d=explode(" ",$c[0]);$e=$d[0];$f=$d[1];unset($c[0]);$g=0;foreach($c as $h){$b[$g]=str_split($h);++$g;}for($i=0;$i<$f;++$i){for($j=0;$j<$e;++$j){if($b[$i][$j]=='o'){$k=$j;$l=$i;$b[$i][$j]=' ';}}}if($b[$l+1][$k]!='#'){$b[$l+1][$k]='o';}else if($b[$l+1][$k+1]!='#'){$b[$l+1][$k+1]='o';}else{$b[$l][$k+1]='o';}echo"$e $f\n";for($i=0;$i<$f;++$i){for($j=0;$j<$e;++$j){echo $b[$i][$j];}echo "\n";}

ここで実際にコードパッドで見ることができます

編集:上記のコードパッドとコードを変更して、oではなく0を出力していたため、出力をプログラムにフィードバックしようとしたときに問題が発生しました。今修正し、1文字保存しました!


0

Groovyの- 263の 261 256文字

ゴルフ。ファイルを文字列に読み取り、関数pを使用して関数をエミュレートしますString.putAtIndex(index,value)

o="o"
b=" "
s=new File(args[0]).text
z={s.size()-it}
s=s[0..z(2)]
w=s.find(/\n.*?\n/).size()-1
p={i,v->s=s[0..i-1]+v+((i<z(0)-2)?s[i+1..z(1)]:"")}
try{
t=s.indexOf o
i=w+t
j=i+1
x=t+1
(s[i]==b)?x=i:(s[j]==b)?x=j:0
p x,o
p t,b
}catch(Exception e){}
print s

未ゴルフ(やや):

o = "o"
b = " "
s = new File(args[0]).text
z = {s.size()-it}
s = s[0..z(2)]
w = s.find(/\n.*?\n/).size()-1

putAtIndex = { i,val -> 
    s = s[0..i-1] + val + ((i<z(0)-2)?s[i+1..z(1)]:"") 
}

try {
    t=s.indexOf o
    i=w+t
    j=i+1
    x=t+1
    // default x as horizontal move
    // check for (a) directly below (b) below and over one
    (s[i]==b) ? x=i : ( (s[j]==b) ? x=j : 0)
    putAtIndex x,o
    putAtIndex t,b
} catch (Exception e) {}
print s

いいね 私は言語を知りませんが、のtry{代わりにtry {とのcatch(Exception代わりに書く場合、(少なくとも)2バイトを取り除くことができるとほぼ確信していますcatch (Exception
クリストフベームヴァルダー14

確かに!ノートのおかげで....
マイケル・イースター

0

R、234

require(stringr)
g=scan(,"")
g=do.call(rbind,strsplit(str_pad(g,m<-max(nchar(g)),"r"),""))
if(g[(x<-which(g=="o"))+1]==" "){g[x+1]="o";g[x]=""}else{if(!is.na(g[x+1])){g[x+(n<-nrow(g))]="o";g[x]=""}}
for(i in 1:n) cat(g[i,],"\n",sep="")

文字列操作はRの最強点ではありません。

より読みやすい:

require(stringr) # load package `stringr`, available from CRAN. required for `str_pad`
g=scan("")       # read input from console
g=do.call(       # applies the first argument (a function) to the second argument (a list of args to be passed) 
  rbind,         # "bind" arguments so that each one becomes the row of a matrix
  strsplit(      # split the first argument by the second
    str_pad(g,max(nchar(g)),"r"," "), # fill each row with whitespace
    "")
)
if(g[(x<-which(g=="o"))+1]==" ") { # if the next element down from the "o" is " "...
  g[x+1]="o";g[x]=""               # make it an "o" and replace the current element with ""
} else {
  if(!is.na(g[x+1])) {             # if the next element down is not empty (i.e. out of range)
    g[x+nrow(g)]="o"; g[x]=""      # move "o" right
  }
}
for(i in 1:n) cat(g[i,],"\n",sep="") # print to console

0

C(182)

char b[1024],*x,*n;main(z){read(0,b,1024);n=index(b,10)+1;x=index(n,'o');z=index(n,10)-n;n=x+z+1;if(n[1]){if(*n==32)*n='o';else if(n[1]==32)n[1]='o';else x[1]='o';*x=32;}printf(b);}

または、実際にコードを読みたい場合:

char b[1024],*x,*n; //1024 byte buffer hard coded
main(z){
    read(0,b,1024);
    n=index(b,10)+1; //start of line 2
    x=index(n,'o');
    z=index(n,10)-n; //10='\n'
    n=x+z+1; //reusing n
    if(n[1]){ //if not 0
        if(*n==32) //32=' '
            *n='o';
        else if(n[1]==32)
            n[1]='o';
        else
            x[1]='o';
        *x=32;
    }
    printf(b);
}

0

Clojure-366文字

正規表現なし。「d」という名前の必須入力ファイル。ゴルフ:

(def s(slurp "d"))(def w(-(.length(re-find #"\n.*?\n" s))2))(def t(.indexOf s "o"))(def i(+ t w 1))(defn g[i,j,x,c](cond (= x i) \ (= x j) \o :else c))(defn j[i,j] (loop[x 0](when(< x (.length s))(print(g i j x (.charAt s x)))(recur(inc x)))))(try(cond(= \ (.charAt s i))(j t i)(= \ (.charAt s (inc i)))(j t (inc i)):else (j t (inc t)))(catch Exception e (print s)))

ゴルフをしていない:

(def s (slurp "d"))
(def w (- (.length (re-find #"\n.*?\n" s)) 2))
(def t (.indexOf s "o"))
(def i (+ t w 1))
(defn g [i,j,x,c] (cond (= x i) \ (= x j) \o :else c))

(defn j [i,j] (loop [x 0]
     (when (< x (.length s))
     (print (g i j x (.charAt s x))) (recur (inc x)))))

(try (cond (= \ (.charAt s i)) (j t i)
           (= \ (.charAt s (inc i))) (j t (inc i))
           :else (j t (inc t)))(catch Exception e (print s)))

サンプル実行(簡潔にするため、1つのケースのみ):

bash-3.2$ cat d
6 7
#     
#     
#     
## o  
####  
####  
##### 

bash-3.2$ java -jar clojure-1.6.0.jar hill.clj 
6 7
#     
#     
#     
##    
####o 
####  
##### 

私は初心者です。提案を歓迎します。


0

MATLAB、160

function r(f)
F=cell2mat(table2array(readtable(f)));
m=@(d)mod(d-1,size(F,1));C=find(F=='o');P=find(F==' ');N=min(P(P>C&m(P)>=m(C)));F([C,N])=F([N,C]);
disp(F);

苦しい部分はファイル入力です。実際の計算は114バイトのみです。

function F=r(F)
m=@(d)mod(d-1,size(F,1));C=find(F=='o');P=find(F==' ');N=min(P(P>C&m(P)>=m(C)));F([C,N])=F([N,C]);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.