언덕 아래로 굴러가는 바위를 계산


17

소개

시시 푸스는 최근 직장에서 어려움을 겪고있었습니다. 그는 결코 아무것도하지 않는 것처럼 보이며이 문제에 대한 해결책을 찾고 싶습니다.

그의 현재 고용은 언덕 위로 바위를 굴려야합니다. 그는 일반적으로 자신의 일을 잘하지만 언덕 꼭대기에 가까워 질 때마다 다시 굴러 떨어집니다.

그는 자신의 일에 정말로 좌절하고 있으며 컴퓨터가 언덕을 굴러 내리는 바위를 시뮬레이트함으로써 과학적으로 문제를 해결하려고합니다.

Sisyphus가 프로그래밍에 특히 좋지 않은 경우가 발생하므로 그를 도울 수 있습니까?

도전

이 어리석은 소개 후에는 사업을 시작하겠습니다. 프로그램은 다음과 유사한 언덕과 바위의 그림을 받게됩니다.

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

어디는 #언덕의 일부를 나타내고 o바위를 나타냅니다.

이제 rock 1 레이어를 아래로 이동시키는 프로그램을 구현해야합니다. 예를 들어, 위의 출력은 다음과 같아야합니다.

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

가로로 균일 한 영역이 있으면 언덕이 가로로 굴러가므로 ...

o
######## 

... 그냥 돌을 옆으로 굴려 요.

 o
######## 

수직 영역이 있으면 암석이 한 단계 아래로 떨어 지므로 ...

#o
#
#
##### 

... 생산할 것이다 ...

#
#o
#
##### 

또한 이미지 위의 한 줄에 이미지의 너비와 높이를 각각받습니다. 완성 된 샘플 입력은 다음과 같습니다.

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

(여기에서 공백은 공백입니다. 텍스트를 선택하고 무슨 뜻인지 확인하십시오.)

일부 세부 사항

  • 프로그램을 실행할 때 바위가 이미 마지막 줄에 있으면 프로그램을 종료하거나 변경되지 않은 입력을 출력하도록 선택할 수 있습니다
  • 언덕은 아래로만 내려갑니다
  • 프로그램은 출력을 치수와 함께 입력과 정확히 동일하게 형식화해야하므로 프로그램의 출력을 자체로 파이프하면 다음 단계를 계산합니다.

  • 항상 맨 아래로가는 방법이 있다고 가정 할 수 있으므로 경로가 "차단 된"입력은 정의되지 않은 동작을 유발할 수 있습니다

  • 마지막 줄에 항상 공백이 있다고 가정 할 수 있습니다. 바위는 "휴식"해야하므로 프로그램을 몇 번 호출 한 후 항상 출력을 파이핑하면 마지막 줄의 바위로 끝나야합니다.

  • 원하는 형식 (stdin, file, ...)으로 입력을 수락 할 수 있습니다. WHOLE 프로그램을 게시해야합니다 (따라서 사전 초기화 된 모든 변수는 코드로 계산됩니다).

  • 줄은로 끝납니다 \n.

  • 여기에 예제 입력을 얻을 수 있습니다 (공백을 올바르게 복사하십시오!)

  • 이것은 이므로 최소 바이트로 작업 제출이 이깁니다.

  • 수상자는 2014 년 7 월 26 일에 선정됩니다. 그 후에 솔루션을 게시 할 수는 있지만 이길 수는 없습니다.

질문이 있으시면 의견에 알려주십시오.

행복한 골프!


마지막 예에서와 같이 후행 공백이 있습니까? (다른 사람들이 없기 때문에)
Martin Ender

@ m.buettner 마지막 ​​예제에서는 9 #초 밖에 없으므로 너비가 10이기 때문에 끝에 하나의 공간이 있습니다.이 경우 (몇 번의 반복 후) 공백이있는 곳에 바위가 놓입니다 (그래서 맨 아래). -오른쪽 코너).
Christoph Böhmwalder

예, 다른 사례가 아니기 때문에 항상 그런 경우 라고 생각할 수 있는지 궁금합니다 . (즉, 다른 예제에는 공백이 전혀 없습니다.)
Martin Ender

6
"Rock and Roll"이라고 부르는 좋은 기회를
놓쳤다

1
@HackerCow 당신이 맞아요. 캐릭터를 제거하여 수정 : D
Martin Ender

답변:


35

정규식 (.NET, Perl, PCRE, JavaScript, ... 향기), 25 바이트

예, 정규 표현식이 유효한 프로그램인지 여부에 관계없이 다시 논쟁을 불러 일으킬 것입니다. 그러나 나는 이것을 선점하고이 제출이 재미를위한 것이며 우승자를 위해 고려할 필요는 없다고 말할 것입니다. (맨 아래의 31 바이트 Perl 변형과 반대로).

그래서 여기에 정규식 대체 솔루션이 있습니다.

패턴 (후행 공백 참고) :

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

교체 (선행 공간 참고) :

 $1o

바이트 수는 둘의 합입니다.

http://regexhero.net/tester/ 에서 테스트 할 수 있습니다 . 붙여 넣을 때 Unix 스타일 줄 끝을 선택하고 "붙여 넣은 서식 유지"를 선택하십시오. 여전히 작동하지 않으면 Windows 스타일 줄 끝을 붙여 넣은 것입니다. 이 경우 가장 쉬운 해결 방법 은 패턴에서 교체 \n하여 \r\n작동하는지 확인하는 것입니다.

이것을 사용 하는 48 바이트 ECMAScript 6 기능 은 다음과 같습니다.

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

마지막으로 실제 프로그램도 있습니다. 그것은 31 바이트 의 Perl입니다 (의 2 바이트 p0플래그를 포함합니다; Ventero 덕분에 제안했습니다!).

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

테스트하고 싶다면 파일로 저장하지 마십시오.

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

불행히도 (온라인 테스터에서) 나를 위해 작동하지 않습니다. 항상 바위를 오른쪽으로 움직입니다. 그러나 40 바이트는 시작이 굉장히 어렵습니다.
Christoph Böhmwalder

@HackerCow 당신 말이 맞아, 방금 문제가 있음을 알았습니다. 고치기 ...
Martin Ender

@HackerCow 아니, 난 당신이 Windows 스타일의 라인 엔딩을 붙여 넣으면 그래서 작업 (교체하려고하지 않는, 끝 라인을 덮어 씁니다 "서식 유지"가 실제로 작동 생각하지만, \n\r\n)
마틴 청산

나를 위해 바위가 오른쪽 벽에있을 때 떨어지지 않습니다. 후행 공백이있는 경우에만 일치합니다.
BrunoJ

4
이걸 어떻게 이길까요? 훌륭한 솔루션
qwr

3

파이썬-190

너무 많은 변수와 함께 슬라이싱 및 연결 공포. 나는 이것이 더 골프화 될 수 있다고 확신하지만, 현명한 파이썬 함수는 생각할 수 없다. 입력은 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)

파이썬 문자열은 변경할 수 없으므로 이전의 모든 문자, 새 문자 및 이후의 모든 문자를 연결하여 문자를 바꿉니다. 언덕 너비와 색인을 사용하여 바위가 어디로 굴려야하는지 결정합니다.


3
내 눈이 아프다. +1
Christoph Böhmwalder

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 입니다. 입력 상자, 입력 문자열, 버튼 등을 계산하면 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
"이동"을 반복해서 클릭하십시오
"이동"을 반복해서 클릭하십시오.

방법

String.match ()를 사용하여 언덕을 5 부분으로 나눈 다음 하나 또는 두 부분을 변경합니다. 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

파이썬 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))))))

나는 약간의 개선을했지만 여전히 끔찍합니다. 이것을 파이썬 3으로 변환하여 몇 바이트를 더 절약 할 수는 있지만 논쟁 할 수는 없습니다.

먼저, 나는 바위를 찾습니다. 바로 아래의 문자가 인 경우의 '#'모든 인스턴스를로 'o '바꿉니다 ' o'. 마지막에 여분의 공간이 보장되므로 항상 바위를 오른쪽으로 이동합니다.

방금 수행했는지 여부에 관계없이 전체 그리드를로 바꿉니다 zip(*m). 그럼, 또 다른 교체 할 'o '과를 ' o'. 바위 오른쪽에 공간이 있으면 실제 그리드에 그 아래에 공간이 있으므로 이동합니다. 그런 다음 다시 바꾸어 인쇄합니다.


이것이 바위의 오른쪽 아래에 빈 공간이 있고 대각선으로 이동하는 OP의 세 번째 예를 어지럽히 지 않습니까?
손잡이

@dor하지 말아야합니다. 아래 공간이 #인 경우 오른쪽으로 만 이동하고 세로로 이동하기 전에 확인을 수행합니다.
undergroundmonorail

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

어 wk, 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";}

당신은 그것을 볼 수 있습니다 여기 codepad에 대한 조치에

편집 : o 대신 0을 출력하는 것처럼 코드 패드와 위의 코드가 변경되어 출력을 프로그램으로 다시 공급하려고 할 때 문제가 발생했습니다. 지금 고쳐서 하나의 문자를 저장했습니다!


0

그루비 - 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

좋은. 나는 언어를 잘 모르겠지만, 당신이 쓰는 경우에 나는 거의 확실 당신은 (적어도) 2 바이트 제거 할 수있어 try{대신 try {하고 catch(Exception대신 catch (Exception.
Christoph Böhmwalder

과연! 메모 주셔서 감사합니다 ....
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="")

문자열 조작은 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

클로저-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)))

샘플 실행 (간단히 한 경우 만) :

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.