Berechnen Sie einen Stein, der einen Hügel hinunter rollt

15

Einführung

Sisyphus hatte in letzter Zeit einige Probleme bei der Arbeit. Es scheint, als würde er einfach nie etwas erledigen und würde gerne eine Lösung für dieses Problem finden.

Seine jetzige Beschäftigung erfordert es, einen Stein einen Hügel hinauf zu rollen. Normalerweise macht er seine Arbeit gut, aber jedes Mal, wenn er sich der Spitze des Hügels nähert, rollt es wieder runter.

Er ist sehr frustriert von seiner Arbeit und möchte das Problem wissenschaftlich lösen, indem er einen Computer den Stein simulieren lässt, der den Hügel hinunter rollt.

Es kommt also vor, dass Sisyphus nicht besonders gut programmiert, also können Sie ihm vielleicht helfen?

Die Herausforderung

Nach dieser dummen Einführung kommen wir zur Sache. Ihr Programm erhält eine Abbildung des Hügels und des Felsens, die ungefähr so ​​aussieht:

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

Wo #repräsentiert ein Teil des Hügels und orepräsentiert den Felsen.

Sie müssen jetzt ein Programm implementieren, das die Rock 1-Ebene nach unten bewegt. Zum Beispiel sollte die Ausgabe des oben genannten sein:

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

Wenn es einen horizontal ebenen Bereich gibt, rollt der Hügel nur horizontal, also ...

o
######## 

... dies würde den Stein nur zur Seite rollen lassen.

 o
######## 

Wenn es eine vertikale Fläche gibt, fällt der Stein eine Stufe herunter, also ...

#o
#
#
##### 

...ergäbe...

#
#o
#
##### 

Sie erhalten auch die Breite und Höhe des Bildes jeweils in einer Zeile über dem Bild. Insgesamt würde unsere Beispieleingabe also so aussehen:

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

(Beachten Sie, dass die Leerzeichen hier Leerzeichen sind. Wählen Sie den Text aus und sehen Sie, was ich meine.)

Ein paar Details

  • Befindet sich der Rock beim Ausführen des Programms bereits in der letzten Zeile, können Sie entweder das Programm beenden oder die unveränderte Eingabe ausgeben
  • Der Hügel geht immer nur bergab
  • Ihr Programm sollte die Ausgabe genauso formatieren wie die Eingabe (einschließlich der Abmessungen). Wenn Sie also die Ausgabe des Programms an sich selbst weiterleiten, berechnet es den nächsten Schritt.

  • Sie können davon ausgehen, dass es immer einen Weg nach unten gibt, sodass Eingaben, bei denen der Pfad "blockiert" ist, undefiniertes Verhalten verursachen können

  • Sie können davon ausgehen, dass in der letzten Zeile immer ein Leerzeichen steht. Der Stein sollte dort "ruhen". Nachdem Sie das Programm einige Male aufgerufen haben und die Ausgabe immer in sich selbst weitergeleitet haben, sollten Sie den Stein in der letzten Zeile an der Stelle ablegen, an der er sich zuvor befunden hat.

  • Sie können Eingaben in jeder beliebigen Form akzeptieren (stdin, file, ...). Sie müssen das GANZE Programm veröffentlichen (so dass alle vorinitialisierten Variablen als Code gelten).

  • Die Zeilen enden mit \n.

  • Sie können einige Beispiel - Eingänge erhalten hier (stellen Sie sicher , dass Sie die Räume richtig zu kopieren!)

  • Das ist , also gewinnt die funktionierende Vorlage mit den wenigsten Bytes .

  • Der Gewinner wird am 26. Juli 2014 ausgewählt. Danach können Sie Lösungen posten, aber nicht gewinnen

Wenn Sie Fragen haben, lassen Sie es mich in den Kommentaren wissen.

Viel Spaß beim Golfen!

Christoph Böhmwalder
quelle
Wird es eine nachgestellte Spalte mit Leerzeichen geben, wie in Ihrem letzten Beispiel? (weil die anderen es nicht haben)
Martin Ender
@ m.buettner Im letzten Beispiel sind es nur 9 #s, so dass am Ende ein Leerzeichen steht, da die Breite 10 beträgt. In diesem Fall würde der Stein (nach einigen Iterationen) dort liegen, wo sich das Leerzeichen befindet (also unten) -rechte Ecke).
Christoph Böhmwalder
Ja, mir ist klar, ich habe mich nur gefragt, ob wir davon ausgehen können, dass dies immer der Fall ist, weil es nicht für Ihre anderen Beispiele ist. (Davon abgesehen haben Ihre anderen Beispiele überhaupt kein Leerzeichen.)
Martin Ender
6
Verpasste eine großartige Chance, es "Rock and Roll" zu nennen
qwr
1
@ HackerCow du hast recht. Behebung durch Entfernen eines Zeichens: D
Martin Ender

Antworten:

33

Regex (.NET, Perl, PCRE, JavaScript, ...), 25 Byte

Ja, dies wird wieder einige Debatten auslösen, ob ein regulärer Ausdruck ein gültiges Programm ist, aber ich gehe dem zuvor und sage, dass diese Einreichung nur zum Spaß ist und nicht für den Gewinner in Betracht gezogen werden muss. (Im Gegensatz zur 31-Byte-Perl-Variante unten;).)

Hier ist also eine reine Regex-Ersatzlösung.

Muster (Leerzeichen beachten):

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

Ersetzung (beachten Sie das führende Leerzeichen):

 $1o

Die Byteanzahl ist für die Summe der beiden.

Sie können es unter http://regexhero.net/tester/ testen . Stellen Sie sicher, dass Sie Zeilenenden im Unix-Stil auswählen und die eingefügte Formatierung beim Einfügen beibehalten. Wenn es immer noch nicht funktioniert, haben Sie immer noch Zeilenenden im Windows-Stil eingefügt. Die einfachste Lösung ist in diesem Fall zu ersetzen , \nmit \r\nin dem Muster zu sehen , dass es funktioniert.

Hier ist eine 48-Byte- ECMAScript 6-Funktion, die dies verwendet

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

Endlich habe ich auch ein aktuelles Programm. Es sind 31 Bytes Perl (einschließlich zwei Bytes für pund 0Flags; danke an Ventero für den Vorschlag!).

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

Wenn Sie es testen möchten, speichern Sie es nicht einmal in einer Datei

perl -p0e 's/o(( *)\n#*)(?=\2) |o / $1o/' < hill.txt
Martin Ender
quelle
Funktioniert bei mir leider nicht (im Online-Tester). Es bewegt einfach immer den Stein nach rechts. 40 Bytes sind ein guter Anfang, der schwer zu schlagen sein wird!
Christoph Böhmwalder
@HackerCow Du hast Recht, ich habe gerade bemerkt, dass es ein Problem gibt. Fixing ...
Martin Ender
@HackerCow Nein , ich denke , dass es tatsächlich funktioniert, aber „Formatierung beibehalten“ überschreibt die Zeilenende, also wenn Sie im Windows-Stil Zeilenenden fügen es nicht funktioniert (versuchen Sie ersetzen \nmit \r\n)
Martin Ender
Für mich fällt der Stein nicht, wenn er gegen die rechte Wand stößt. es stimmt nur überein, wenn es ein nachgestelltes Leerzeichen hat.
BrunoJ
4
Wie soll ich das schlagen? Tolle Lösung
qwr
3

Python - 190

Slicing- und Verkettungs-Horror, zusammen mit viel zu vielen Variablen. Ich bin mir sicher, dass man mehr Golf spielen kann, aber mir fallen momentan keine cleveren Python-Funktionen ein. Die Eingabe wird in einer Zeichenfolge gespeicherts .

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)

Da Python-Strings unveränderlich sind, ersetze ich ein Zeichen, indem ich alle Zeichen davor, mein neues Zeichen und alle Zeichen danach verkette. Anhand der Hügelbreite und der Indexierung bestimme ich, wohin der Fels rollen soll.

qwr
quelle
3
Meine Augen tun weh. +1
Christoph Böhmwalder
2

Ruby, 65/55 Zeichen

Ich denke, ich würde sehen, wie lange eine Lösung dauert, die das Problem nicht einfach in den Griff bekommt.

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

Es ist erwartungsgemäß nicht so kurz wie die Regex-Lösung von m.buettner - aber auch nicht viel länger.

Bei Verwendung von Interpreter-Flags kann dies auf 55 Zeichen verkürzt werden (53 für den Code, 2 für die Flags):

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

Führen Sie den Code wie folgt aus:

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

HTML JavaScript - 251 Zeichen

( 251, wenn Sie den Code in den einfachen Anführungszeichen zählen, die die Eingabe lesen und die Ausgabe zurückgeben. 359, wenn Sie das Eingabefeld, die Eingabezeichenfolge, die Schaltfläche usw. zählen. 192, wenn Sie genau das zählen, erledigt die Arbeit.)

Golf Code:

<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
Klicken Sie immer wieder auf "Los"
Klicken Sie immer wieder auf "Go".

Methode

Ich verwende String.match (), um einen Hügel in 5 Teile aufzuteilen, dann ändere ich ein oder zwei Teile. Ich lerne JavaScript, daher sind alle Vorschläge willkommen.

Lesbarer Code

<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>
JeffSB
quelle
1

Python 2 - 289 252 Bytes

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

Ich habe einige bedeutende Verbesserungen vorgenommen, aber das ist immer noch schrecklich. Ein paar weitere Bytes können durch Konvertieren in Python 3 gespeichert werden, aber ich kann nicht bearbeitet werden.

Zuerst finde ich den Felsen. Wenn das Zeichen direkt darunter steht '#', ersetzen Sie jede Instanz von 'o 'durch ' o'. Da am Ende garantiert ein zusätzliches Leerzeichen vorhanden ist, wird der Stein immer nach rechts verschoben.

Egal, ob ich das gerade getan habe oder nicht, ich transponiere das gesamte Raster mit zip(*m). Dann mache ich noch einen Ersatz 'o 'mit ' o'. Wenn sich rechts vom Felsen ein Feld befindet, bedeutet dies, dass sich im realen Gitter ein Feld darunter befindet, sodass es verschoben wird. Dann transponiere ich zurück und drucke.

untergrundbahn
quelle
Würde dies nicht das dritte Beispiel des OP, in dem rechts und unterhalb des Felsens ein leerer Raum ist, durcheinander bringen und diagonal verschieben?
Türklinke
@dor Sollte es nicht. Ich bewege mich nur nach rechts, wenn der Raum darunter ist #, und ich mache diese Prüfung, bevor ich die Prüfung mache, um mich vertikal zu bewegen.
U-
1

Python (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='')
Ian D. Scott
quelle
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}'

Mehr lesbar

    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.
  }
'
Julian Peeters
quelle
0

PHP 485 484 Zeichen

Ich weiß, dass dies im Vergleich zum Einstieg von m.buettner massiv ist, aber es ist das Beste, was ich im Moment tun kann. Ich denke, es muss eine schnellere Möglichkeit geben, die Eingabezeichenfolge in ein mehrdimensionales Array umzuwandeln, aber jetzt ist es sehr spät.

Und obwohl es nicht wettbewerbsfähig ist, hat mir dieses Rätsel gefallen. Möchte, dass die Erweiterung anzeigt, wo der Ball landet, oder nach einer festgelegten Anzahl von Schritten, möglicherweise nach der Breite und Höhe in der Eingabezeile hinzugefügt. Könnte das sehr leicht zu dieser Version hinzufügen.

Hier ist mein Code: Die Eingabe erfolgt in der ersten Variablen.

<?
$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";}

Sie können es hier in Aktion auf dem Codepad sehen

Bearbeiten: Codepad und Code oben geändert, da 0 anstelle von o ausgegeben wurde, was zu Problemen führte, als ich versuchte, die Ausgabe wieder in das Programm einzuspeisen. Jetzt behoben und ein Zeichen gespeichert!

Paul Drewett
quelle
0

Groovy - 263 261 256 Zeichen

Golf gespielt. Lesen Sie die Datei in einen String und verwenden Sie eine Funktion p, um eine Funktion zu emulieren 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

Ungolfed (etwas):

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
Michael Easter
quelle
Nett. Ich kenne die Sprache nicht, aber ich bin mir fast sicher, dass Sie (mindestens) zwei Bytes loswerden können, wenn Sie try{anstelle von try {und catch(Exceptionanstelle von schreiben catch (Exception.
Christoph Böhmwalder
Tatsächlich! Danke für den Hinweis ....
Michael Ostern
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="")

Die Manipulation von Strings ist nicht die größte Stärke von R.

Besser lesbar:

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
Shadowtalker
quelle
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);}

Oder, wenn Sie den Code tatsächlich lesen möchten:

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);
}
Ian D. Scott
quelle
0

Clojure - 366 Zeichen

Ohne Regex. Erforderliche Eingabedatei mit dem Namen "d". Golf gespielt:

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

Ungolfed:

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

Probelauf (nur ein Fall, der Kürze halber):

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

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

Ich bin ein Neuling. Vorschläge sind willkommen.

Michael Easter
quelle
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);

Der schmerzhafte Teil ist die Dateieingabe. Die tatsächliche Berechnung würde nur 114 Bytes betragen:

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]);
knedlsepp
quelle