ทำนายก้อนหินที่ตกลงมา


18

ในการท้าทายนี้คุณจะได้รับแผนที่ภูมิประเทศสองมิติที่มองจากด้านข้าง น่าเสียดายที่บางส่วนของภูมิประเทศลอยอยู่ในอากาศซึ่งหมายความว่าพวกมันจะพังทลาย งานของคุณคือการทำนายว่าพวกเขาอยู่ที่ไหน

การป้อนข้อมูล

ข้อมูลที่คุณป้อนคือสตริงที่คั่นด้วยบรรทัดใหม่หนึ่งรายการขึ้นไปที่มีความยาวเท่ากันประกอบด้วยอักขระ#(เครื่องหมายตัวเลขหมายถึงหิน) หรือ.(จุดหนึ่งหมายถึงพื้นที่ว่าง)

ผลลัพธ์

เอาต์พุตของคุณมีรูปแบบเดียวกับอินพุต แต่มีการแก้ไขต่อไปนี้ ให้เราดูสตริงอินพุตเป็นตารางหินสองมิติ ร็อคในการป้อนข้อมูลที่เชื่อมต่อกับด้านล่างของตารางโดยเส้นทางของหินที่อยู่ติดกันที่ทุกคนเป็นบริษัท ; หินอื่น ๆหลวม หินที่อยู่ติดกันในแนวทแยงมุมจะไม่ถูกพิจารณาว่าเป็นสิ่งที่อยู่ติดกัน หินที่หลวมทั้งหมดจะตกลงมาและจบลงด้วยการวางซ้อนกันบนหินที่มั่นคงหรือแถวล่าง หินที่หลวมนั้นไม่ได้ยึดติดกันดังนั้นมันจึงตกแยกกันไม่เป็นรูปร่างใหญ่ เอาต์พุตเป็นกริดที่เกิดขึ้น

ตัวอย่าง

  • การป้อนข้อมูล

    ..###.
    .##.#.
    .#....
    .##.#.
    

    ไม่มีหินที่หลวมดังนั้นผลลัพธ์จึงเหมือนกัน

  • การป้อนข้อมูล

    ...#..
    .#..#.
    .#..##
    .#...#
    .#####
    .#...#
    

    มีหินหลวมหนึ่งก้อนที่ด้านบนซึ่งตกลงบนก้อนหินที่มั่นคงใต้นั้น ผลลัพธ์คือ

    ......
    .#..#.
    .#..##
    .#.#.#
    .#####
    .#...#
    
  • การป้อนข้อมูล

    .#####....
    .#....####
    ###.###..#
    #.#...##..
    .####..#.#
    ......###.
    ..#...#..#
    ..#...#..#
    

    มีกลุ่มหินก้อนใหญ่ทางด้านซ้าย กลุ่มพังทลายลงเมื่อก้อนหินตกลงดังนั้นผลลัพธ์ก็คือ

    ..........
    ....######
    ..#.###..#
    . #...##..
    .##....#..
    .##...####
    ####..#..#
    #####.#..#
    

ชี้แจง

  • คุณสามารถนำอินพุตจาก STDIN และเอาต์พุตไปยัง STDOUT หรือเขียนฟังก์ชัน
  • นี่คือโค้ดกอล์ฟดังนั้นโปรแกรมที่สั้นที่สุด (เป็นไบต์) จึงเป็นผู้ชนะ
  • ช่องโหว่มาตรฐานไม่ได้รับอนุญาต

คำตอบ:


12

CJam, 180 ... 133 101 ... 94 90 87 ไบต์

qN/~'#/S*_,):L;]N*_,_,*{:A1$='#={[W1LL~)]Af+{W>},1$f=S&,{ASct}*}*}/N/z{S/{$W%}%'#*}%zN*

มีสนามกอล์ฟจำนวนมากที่เป็นไปได้ แต่ฉันต้องการโพสต์ก่อนหลังจากที่ให้มันทำงานอย่างสมบูรณ์

ดูสิ! ไม่มีแถบเลื่อน!

นำกริดหิน (ประกอบด้วย.และ#ไม่มีบรรทัดใหม่ต่อท้าย) จาก STDIN และพิมพ์เอาต์พุตไปยัง STDOUT

UPDATE : ใช้เติมน้ำท่วมบางส่วนที่ไม่มีประสิทธิภาพ แต่สั้นลงเพื่อหาก้อนหินที่มั่นคง

UPDATE 2 : เปลี่ยนอัลกอริทึมในการทำให้หินตกลงไป สั้นลงมากแล้วตอนนี้!

ปรับปรุง 3 : การเพิ่มประสิทธิภาพเล็ก ๆ น้อย ๆ หลายอย่างและในที่สุดฉันก็สามารถลดจำนวนไบต์ลงเหลือครึ่งหนึ่งของรหัสต้นฉบับได้!

มันทำงานอย่างไร :

qN/~'#/S*_,):L;]N*             "Preparations";
qN/~                           "Read the input, split by new line and expand the array";
    '#/S*                      "In the last row, replace # by space";
         _,):L                 "Copy the last row and store length + 1 in L";
              ;]N*             "Pop the length, wrap everything in array and join by \n";

_,_,*{ ... }/                  "Flood fill";
_,                             "Copy the array and calculate its length";
  _,                           "Copy the length and calculate [0 - length] array";
    *                          "Repeat the above array, length times";
     { ... }/                  "Run the code block on each element of the array";

:A1$='#={ ... }*               "Process only #";
:A1$                           "Store the number in A and copy the input array to stack";
    =                          "Get Ath index element from input array";
     '#={ ... }*               "Run the code block if Ath element equals #";

[W1LL~)]Af+{W>},1$f=S&,{ASct}* "Flood fill spaces";
[W1LL~)]Af+                    "Get the indexes of the 4 elements on the cross formed by"
                               "the Ath index";
           {W>},               "Filter out the negative values";
                1$f=           "For each of the index, get the char from input string";
                    S&,        "Check if space is one of the 4 chars from above step";
                       {    }* "Run the code block if space is present";
                        ASct   "Make the Ath character of input string as space";

N/z{S/{$W%}%'#*}%zN*           "Let the rocks fall";
N/z                            "Split the resultant string by newlines and"
                               "transpose the matrix";
   {           }%              "Run the code block for each row (column of original)";
    S/{   }%                   "Split by space and run the code block for each part";
       $W%                     "Sort and reverse. This makes # come down and . to go up";
            '#*                "Join by 3, effectively replacing back spaces with #";
                 zN*           "Transpose to get back final matrix and join by newline";

สำหรับการเติมน้ำท่วมเราวนซ้ำตามความยาวกริดทั้งหมด (กริด) เท่า ในการวนซ้ำแต่ละครั้งเรารับประกันว่าจะแปลงอย่างน้อย 1 #ซึ่งสัมผัสโดยตรงกับช่องว่าง(ช่องว่าง) Space ที่นี่แสดงถึงกลุ่มหินที่มั่นคง ดังนั้นในตอนท้ายของความยาว (กริด) การทำซ้ำเรารับประกันว่าจะมีหินที่แน่นหนาแสดงด้วยช่องว่าง

ลองออนไลน์ได้ที่นี่


15

Perl 5: 98

98 รวมถึง 2 ธงบรรทัดคำสั่ง

#!perl -p0
1while/
/,($x="($`)")=~y!#!.!,s/#(.*
$)/%$1/+s/#$x?%|%$x?#/%$1$2%/s;1while s/#$x\./.$1#/s;y!%!#!

คำอธิบาย:

#!perl -p0 #read entire input to $_ and print at the end
/\n/;($x="($`)")=~y!#!.!; #calculate pattern matching space
                          #between two characters in the same column
                          #looks like "(......)" 
1 while s/#(.*\n$)/%$1/+s/#$x?%|%$x?#/%$1$2%/s;
                          #flood fill solid rock with %
1 while s/#$x\./.$1#/s;   #drop loose rock
y!%!#!                    #change % back to #

@Optimizer ฉันต้องใช้บรรทัดสุดท้ายของการป้อนข้อมูลให้ถูกต้องดู: ideone.com/7E3gQhหากปราศจากความเชื่อมั่นนี้มันจะเป็นหนึ่งในผู้สันโดษ
nutki

1
เอาชนะ CJam เกือบ 30%? น่าอัศจรรย์ ฉันขอแสดงความยินดีกับคุณ
DLosc

@DLosc ไม่ได้อีกต่อไป: P
เครื่องมือเพิ่มประสิทธิภาพ

เอาชนะภาษาที่จำเป็นอื่น ๆ ได้ 100-300%? น่าอัศจรรย์ ฉันขอแสดงความยินดีกับคุณ ;)
DLosc

@DLosc ดูคำตอบข้างต้นฉันจะไม่รวม Perl ในรายการของภาษาที่จำเป็นอีกต่อไป: P
เครื่องมือเพิ่มประสิทธิภาพ

5

JavaScript (ES6) 232

s=>{for(s=[...s+'1'.repeat(r=1+s.search('\n'))];s=s.map((c,p)=>c=='#'&(s[p+1]|s[p-1]|s[p-r]|s[p+r])?f=1:c,f=0),f;);for(;s.map((c,p)=>c=='#'&s[p+r]=='.'&&(s[p]='.',f=s[p+r]=c),f=0),f;);return s.join('').replace(/1/g,rok).slice(0,-r)}

เป็นฟังก์ชั่นที่มีพารามิเตอร์สตริงและส่งคืนสตริง

ในตอนแรกให้เพิ่มแถวด้านล่างของ '1' เพื่อระบุบรรทัดล่าง
การค้นหาลูปแรกสำหรับหินที่ตายตัว (ที่อยู่ใกล้กับ '1') และทำเครื่องหมายว่า '1' เช่นกันการค้นหาจะทำซ้ำจนกว่าจะไม่พบหินที่มั่นคงอีก
การวนซ้ำที่สองย้ายอักขระ '#' ที่เหลือไปยังแถวด้านล่าง ซ้ำอีกครั้งจนกว่าจะไม่สามารถเคลื่อนย้ายหินได้
ในที่สุดให้แทนที่ '1' ด้วย '#' อีกครั้งและตัดแถวด้านล่าง

น้อย golfed

s=>{
  r = 1+s.search('\n');
  s = [...s+'1'.repeat(r)];
  for (; s = s.map((c,p) => c=='#' & (s[p+1]|s[p-1]|s[p-r]|s[p+r])?f=1:c,f=0),f; );
  for (; s.map((c,p) => c=='#' & s[p+r]=='.'&& (s[p] ='.', s[p+r]=c, f=1),f=0),f; );
  return s.join('')
    .replace(/1/g,'#')
    .slice(0,-r)
}

ทดสอบ (คุณสามารถมีหลักฐานของหินที่มั่นคงและสิ่งที่ตกลงมา)

F=
s=>{for(s=[...s+'1'.repeat(r=1+s.search('\n'))];s=s.map((c,p)=>c=='#'&(s[p+1]|s[p-1]|s[p-r]|s[p+r])?f=1:c,f=0),f;);for(;s.map((c,p)=>c=='#'&s[p+r]=='.'&&(s[p]='.',f=s[p+r]=c),f=0),f;);return s.join('').replace(/1/g,rok).slice(0,-r)}

var rok // using rok that is 3 chars like '#'

function update() {
  rok = C.checked ? '@' : '#';
  O.textContent=F(I.textContent)
}

update()
td { padding: 5px }
pre { border: 1px solid #000; margin:0 }
<table><tr><td>Input</td><td>Output</td></tr>
<tr><td><pre id=I>.#####....
.#....####
###.###..#
#.#...##..
.####..#.#
......###.
..#...#..#
..#...#..#</pre></td>
<td><pre id=O></pre>
</td></tr></table>
<input type='checkbox' id=C oninput='update()'>Show firm rocks


3

APL, 130 119

'.##'[1+⊖1↓⍉↑↑{,/{⍵[⍒⍵]}¨x⊂⍨2=x←2,⍵}¨↓ ⍉⊃⌈/(1,¨⍳⍴⊃↓x){x←⍵⋄(⍺⌷x)∧←2⋄x≡⍵:x⋄⊃⌈/((⊂⍴⍵)⌊¨1⌈(,∘-⍨↓∘.=⍨⍳2)+⊂⍺)∇¨⊂x}¨⊂⊖'#'=x←⎕]

เนื่องจากเป็นไปไม่ได้ (เท่าที่ฉันรู้) เพื่อป้อนบรรทัดใหม่เมื่อได้รับพร้อมท์โปรแกรมนี้ใช้เมทริกซ์อักขระเป็นอินพุต

อัลกอริทึมที่ใช้เป็นครั้งแรกที่แปลงไปเป็นเมทริกซ์ไบนารี ( 0คืออากาศและ1เป็นร็อค) แล้วน้ำท่วมเติมจากแถวด้านล่างเพื่อทำเครื่องหมายหิน บริษัท 2เป็น จากนั้นแบ่งแต่ละคอลัมน์เป็น "ช่องว่างระหว่างก้อนหินมั่นคง" และจัดเรียงแต่ละพาร์ติชันเพื่อทำให้หินหลวม "ตกลงไปในอากาศ"

แก้ไข 1: ตีกอล์ฟโดยใช้อัลกอริทึมเติมน้ำท่วมที่แตกต่าง


ทดสอบการทำงาน

เรียกใช้ 1

กำหนดเมทริกซ์อักขระAและพิมพ์:

      A←↑('.#####....') ('.#....####') ('###.###..#') ('#.#...##..') ('.####..#.#') ('......###.') ('..#...#..#') ('..#...#..#')
      A
.#####....
.#....####
###.###..#
#.#...##..
.####..#.#
......###.
..#...#..#
..#...#..#

จากนั้นป้อนAเข้าสู่โปรแกรม:

      '.##'[1+⊖1↓⍉↑↑{,/{⍵[⍒⍵]}¨x⊂⍨2=x←2,⍵}¨↓⍉(1,¨⍳⊃⌽⍴x){⍵≡y←⊃⌈/x←⍺{x←⍵⋄(⍺⌷x)∧←2⋄x}¨⊂⍵:y⋄((⊂⍴⍵)⌊¨1⌈,(,∘-⍨↓∘.=⍨⍳2)∘.+⍺/⍨x≢¨⊂⍵)∇y}⊖'#'=x←⎕]
⎕:
      A
..........
....######
..#.###..#
..#...##..
.##....#..
.##...####
####..#..#
#####.#..#

เรียกใช้ 2

      A←↑('#######')('#.....#')('#.#.#.#')('#.....#')('#######')
      A
#######
#.....#
#.#.#.#
#.....#
#######
      '.##'[1+⊖1↓⍉↑↑{,/{⍵[⍒⍵]}¨x⊂⍨2=x←2,⍵}¨↓⍉(1,¨⍳⊃⌽⍴x){⍵≡y←⊃⌈/x←⍺{x←⍵⋄(⍺⌷x)∧←2⋄x}¨⊂⍵:y⋄((⊂⍴⍵)⌊¨1⌈,(,∘-⍨↓∘.=⍨⍳2)∘.+⍺/⍨x≢¨⊂⍵)∇y}⊖'#'=x←⎕]
⎕:
      A
#######
#.....#
#.....#
#.#.#.#
#######

2

JS - 443 ไบต์

function g(b){function f(b,c,e){return b.substr(0,c)+e+b.substr(c+1)}function e(d,c){"#"==b[c][d]&&(b[c]=f(b[c],d,"F"),1<d&&e(d-1,c),d<w-1&&e(d+1,c),1<c&&e(d,c-1),c<h-1&&e(d,c+1))}b=b.split("\n");w=b[0].length;h=b.length;for(i=0;i<w;i++)"#"==b[h-1][i]&&e(i,h-1);for(j=h-2;-1<j;j--)for(i=0;i<w;i++)if(k=j+1,"#"==b[j][i]){for(;k<h&&"F"!=b[k][i]&&"#"!=b[k][i];)k++;k--;b[j]=f(b[j],i,".");b[k]=f(b[k],i,"#")}return b.join("\n").replace(/F/g,"#")};

น้ำท่วมทำให้เต็มไปด้วยหินจากด้านล่างจากนั้นนำหินที่ไม่ได้ไหลท่วม ใช้การเรียกซ้ำหลายครั้งเมื่อเติมน้ำท่วมดังนั้นจึงอาจทำให้เบราว์เซอร์ของคุณล่าช้าเล็กน้อย

มันเป็นฟังก์ชั่น - เรียกมันด้วย g("input")

JSFiddle: http://jsfiddle.net/mh66xge6/1/

Ungolfed JSFiddle: http://jsfiddle.net/mh66xge6/


1

Python 3, 364 ไบต์

ฉันแน่ใจว่าอาจถูกบีบออกจากสิ่งนี้ ... แต่มันจะไม่แข่งขันกับ CJam และ Perl ต่อไป

z="%";R=range
def F(r,c,g):
 if z>g[r][c]:g[r][c]=z;[F(r+d%2*(d-2),c+(d%2-1)*(d-1),g)for d in R(4)]
def P(s):
 t=s.split()[::-1];w=len(t[0]);g=[list(r+".")for r in t+["."*w]];[F(0,c,g)for c in R(w)]
 for c in R(w):
  for r in R(len(g)):
   while g[r][c]<z<g[r-1][c]and r:g[r][c],g[r-1][c]=".#";r-=1
 return"\n".join(''.join(r[:w])for r in g[-2::-1]).replace(z,"#")

คล้ายกับคำตอบอื่น ๆ หนึ่งมุมแหลมก็คือว่ามันจะเปลี่ยนตารางคว่ำแรก (เพื่อให้ดัชนีห่วงสะดวกมากขึ้น) และเพิ่มแถวพิเศษและคอลัมน์.(เพื่อหลีกเลี่ยงปัญหาเกี่ยวกับการตัด-1ดัชนี) P(string)ดำเนินการโดยการโทร

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.