Bir tepeden aşağı yuvarlanan bir kayayı hesaplayın


17

Giriş

Sisifos son zamanlarda işte bazı sıkıntılar yaşıyordu. Görünüşe göre hiç bir şey yapmıyor ve bu soruna bir çözüm bulmayı çok ister.

Şu anki istihdamı bir kayayı tepeye yuvarlamayı gerektiriyor. Genellikle işini iyi yapar, ancak her tepenin yakınında olduğunda tekrar yuvarlanır.

İşinden gerçekten sinirleniyor ve bir tepeden aşağı kayayı taklit eden bir bilgisayara sahip olarak sorunu bilimsel olarak çözmek istiyor.

Sisyphus'un programlamada özellikle iyi olmadığı, belki de ona yardımcı olabileceğinizi?

Meydan okuma

Bu aptalca tanıtımdan sonra işe gelelim. Programınız buna benzer tepenin ve kayanın bir resmini alacak:

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

Burada #tepenin bir bölümünü otemsil eder ve kayayı temsil eder.

Şimdi rock 1 katmanını aşağıya doğru hareket ettiren bir program uygulamak zorundasınız. Örneğin, yukarıdakilerin çıktısı şöyle olmalıdır:

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

Yatay olarak eşit bir alan varsa, tepe yatay olarak yuvarlanır, bu yüzden ...

o
######## 

... bu sadece taşı yana yuvarlar.

 o
######## 

Dikey bir alan varsa, kaya bir adım aşağı düşer, bu yüzden ...

#o
#
#
##### 

...verim verecek...

#
#o
#
##### 

Ayrıca, görüntünün genişliğini ve yüksekliğini sırasıyla görüntünün üzerindeki bir satıra alırsınız. Yani, tam olarak, örnek girdimiz şöyle görünecektir:

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

(Buradaki boşlukun boşluk olduğunu unutmayın. Metni seçin ve ne demek istediğimi görün.)

Bazı detaylar

  • Programı çalıştırırken kaya zaten son satırdayken, programı sonlandırmayı veya değiştirilmemiş girişi çıkarmayı seçebilirsiniz.
  • Tepe aşağı iner
  • Programınız çıktıyı girişle tam olarak aynı şekilde biçimlendirmelidir (boyutlar dahil), bu nedenle programın çıktısını kendisine bağlarsanız bir sonraki adımı hesaplar.

  • Her zaman en alta doğru bir yol olduğunu varsayabilirsiniz, bu nedenle yolun "engellendiği" giriş tanımlanmamış davranışa neden olabilir

  • Son satırda her zaman bir boşluk olduğunu varsayabilirsiniz. Kaya orada "dinlenmeli", bu yüzden programı birkaç kez çağırdıktan sonra, her zaman kendi çıktısını boru haline getirdikten sonra, son satırdaki kaya ile daha önce boşluğun bulunduğu yeri döşemelisiniz.

  • Girişi istediğiniz herhangi bir biçimde kabul edebilirsiniz (stdin, dosya, ...). WHOLE programını yayınlamalısınız (bu nedenle önceden başlatılmış tüm değişkenler kod olarak sayılır).

  • Hatlar ile sonlandırılır \n .

  • Burada bazı örnek girişler alabilirsiniz (boşlukları doğru kopyaladığınızdan emin olun!)

  • Bu , bu yüzden en az bayt ile çalışma gönderme kazanır.

  • Kazanan 26 Temmuz 2014'te seçilecek. Bundan sonra çözüm gönderebilirsiniz, ancak kazanamazsınız

Herhangi bir sorunuz varsa yorumlarda bana bildirin.

Mutlu golf!


Son örneğinizde olduğu gibi boşluktan sonra gelen bir sütun olacak mı? (çünkü diğerlerinde yoktur)
Martin Ender

@ m.buettner Son örnekte sadece 9 #sn vardır, bu nedenle sonunda bir boşluk vardır, çünkü genişlik 10'dur. Bu durumda (birkaç yinelemeden sonra) kaya, boşluğun olduğu yere uzanır (böylece altta) -sağ köşe).
Christoph Böhmwalder

Evet, bunun her zaman böyle olduğunu varsayabilir miyiz diye merak ediyordum , çünkü bu diğer örnekleriniz için değil. (Bununla birlikte, diğer örneklerinizde hiç boşluk bırakmaz.)
Martin Ender

6
"Rock and Roll"
adını

1
@ HackerCow haklısın. Bir karakteri kaldırarak düzeltildi: D
Martin Ender

Yanıtlar:


35

Regex (.NET, Perl, PCRE, JavaScript, ... tatlar), 25 bayt

Evet, bu düzenli bir ifadenin geçerli bir program olup olmadığı konusunda tekrar tartışma yaratacaktır, ancak bunu önceden boşaltacağım ve bu sunumun sadece eğlence için olduğunu ve kazanan için düşünülmesinin gerekmediğini söyleyeceğim. (Alttaki 31 bayt Perl varyantının aksine;).)

İşte burada saf bir regex değiştirme çözümü.

Desen (sondaki boşluğa dikkat edin):

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

Değiştirme (önde gelen boşluğa dikkat edin):

 $1o

Bayt sayısı ikisinin toplamı içindir.

Bunu http://regexhero.net/tester/ adresinden test edebilirsiniz . Yapıştırırken Unix stili satır sonlarını seçtiğinizden ve "yapıştırılan biçimlendirmeyi koru" yu seçtiğinizden emin olun. Hala çalışmıyorsa, Windows stili satır sonlarını yapıştırdınız. Bu durumda en kolay düzeltme,\n ile \r\nçalıştığını görmek desende.

İşte bunu kullanarak 48 bayt ECMAScript 6 işlevi

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

Sonunda gerçek bir programım var. Bu var 31 bayt (iki bayt dahil Perl pve 0!; Öneri için Ventero sayesinde bayrakları).

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

Test etmek istiyorsanız, bir dosyaya bile kaydetmeyin, sadece

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

Maalesef benim için çalışmıyor (çevrimiçi testte). Her zaman kayayı sağa doğru hareket ettirir. 40 bayt harika bir başlangıç ​​olsa da, bu yenmek zor olacak!
Christoph Böhmwalder

@HackerCow Haklısın, sadece bir sorun olduğunu fark ettim. Düzeltme ...
Martin Ender

@HackerCow Hayır Windows tarzı satır sonları yapıştırmak eğer öyleyse bu işi (değiştirmeyi deneyin değil, biten çizgi üzerine yazar "biçimlendirme korumak" aslında çalışır düşünüyorum, ama \nbirlikte \r\n)
Martin Ender

Benim için kaya doğru duvara çarptığında düşmez, yani. yalnızca sondaki boşluğu olduğunda eşleşir.
BrunoJ

4
Bunu nasıl yenebilirim? Great solution
qwr

3

Python - 190

Dilimleme ve birleştirme korkusu, çok fazla değişkenle birlikte. Bunun daha fazla golf oynayabileceğinden eminim, ancak şu anda akıllı bir python işlevi düşünemiyorum. Giriş dizede saklanır 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 dizeleri değişmez olduğu için, önceki tüm karakterleri, yeni karakterimi ve sonraki tüm karakterleri birleştirerek bir karakteri değiştiririm. Kayanın nereye gitmesi gerektiğini belirlemek için tepe genişliğini ve indekslemeyi kullanıyorum.


3
Gözlerim acıyor. +1
Christoph Böhmwalder

2

Ruby, 65/55 karakter

Bir çözümün ne kadar uzun olduğunu görebiliyordum, bu sadece soruna bir normal ifade atmıyor.

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

Beklendiği gibi, m.buettner'in regex çözümü kadar kısa değil - ama çok daha uzun değil.

Yorumlayıcı bayrakları kullanılırken, bu 55 karaktere kısaltılabilir (kod için 53, bayraklar için 2):

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

Kodu şu şekilde çalıştırın:

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

2

HTML JavaScript - 251 karakter

( 251 kodunu girdiyi okuyan ve çıktıyı döndüren tek tırnak içinde sayarsanız. 359 girdi kutusunu, girdi dizesini, düğmeyi vb. Sayarsanız Sayarsanız 192 .

Golf kodu:

<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
"Git" i tekrar tekrar tıklayın
Tekrar tekrar "Git" i tıklayın.

Yöntem

5 parçaya tepeyi kırmak için String.match () kullanır, sonra bir veya iki parçayı değiştiririm. JavaScript öğreniyorum, bu yüzden herhangi bir öneri takdir edilecektir.

Okunabilir Kod

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

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

Bazı önemli iyileştirmeler yaptım ama bu hala korkunç. Python 3'e dönüştürülerek birkaç bayt daha kaydedilebilir, ancak silinebilirim.

İlk olarak, kayayı buluyorum. Hemen altında karakter ise '#', her geçtiği yerde değiştirmek 'o 'ile ' o'. Sonunda fazladan bir boşluk olması garanti edildiğinden, bu her zaman kayayı sağa doğru hareket ettirecektir.

Sadece yapsam da yapmasam da, tüm ızgarayı devrediyorum zip(*m). Sonra, başka bir değiştirme yapmak 'o 'ile ' o'. Kayanın sağında bir boşluk varsa, bu gerçek ızgarada altında bir boşluk olduğu anlamına gelir, böylece hareket eder. Sonra geri alıp yazdırıyorum.


Bu, OP'nin kayanın sağında ve altında boş alan bulunan ve çapraz olarak hareket ettirdiği 3. örneğe zarar vermez mi?
Kapı tokmağı

@dor Yapmamalı. Yalnızca aşağıdaki boşluk varsa sağa hareket ediyorum #ve bu kontrolü dikey olarak hareket ettirmeden önce yapıyorum.
undergroundmonorail

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

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}'

Daha Okunabilir

    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 karakter

Bunun m.buettner girişine göre çok büyük olduğunu biliyorum ama şimdilik yapabileceğim en iyisi. Bence giriş dizesini çok boyutlu bir diziye çevirmek için daha hızlı bir yol olmalı ama şimdi çok geç.

Rekabetçi olmasa da bu bulmacayı beğendim. Uzantının, topun nerede bittiğini veya belirli bir adımdan sonra, belki de giriş satırındaki genişlik ve yükseklikten sonra eklendiğini göstermesini ister. Bunu bu sürüme kolayca ekleyebiliriz.

İşte benim kod: Giriş ilk değişken.

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

Görebilirsiniz burada CodePad üzerinde eylem

Düzenleme: Kod takımı ve yukarıdaki kod yerine o yerine 0 çıktı olarak değiştirildi, ben programa geri beslemeye çalıştığınızda soruna neden oldu. Şimdi düzeltildi ve bir karakter kaydedildi!


0

Harika - 263 261 256 karakter

Golfed. Dosyayı bir String olarak okuyun ve bir işlevi ptaklit etmek için bir işlev kullanın 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

Kurtulmamış (biraz):

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

Güzel. Ben dil bilmiyorum ama yazarsam neredeyse emin (en azından) iki bayt kurtulabilirsiniz ediyorum try{yerine try {ve catch(Exceptionyerine catch (Exception.
Christoph Böhmwalder

Aslında! Not için teşekkürler ....
Michael Easter

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

Dizi manipülasyonu R'nin en güçlü noktası değildir.

Daha okunaklı:

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

Veya kodu gerçekten okumak istiyorsanız:

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 karakter

Normal ifade olmadan. "D" adında gerekli girdi dosyası. golfed:

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

Örnek çalışma (sadece bir vaka, kısalık için):

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

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

Ben bir acemiyim. Öneriler hoş geldiniz.


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

Acı veren kısım dosya girdisidir. Gerçek hesaplama sadece 114 bayt olur:

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]);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.