ตัดพิซซ่าเป็นชิ้น ๆ


16

นี่คือสิ่งที่ฉันคิดว่าคำถามนี้จะเป็นไปได้ก่อนที่ฉันจะอ่านอย่างเต็มที่

นักกอล์ฟกลุ่มหนึ่งเดินเข้าไปใน The Nineteenth Bite Pizzeria และสั่งพิซซ่า มันมาในรูปทรงที่ผิดปกติทำจากสี่เหลี่ยมหน่วย งานของคุณคือช่วยให้พวกเขาหั่นเป็นชิ้น ๆ กล่าวคือชิ้นส่วนต้องมีรูปร่างและขนาดเท่ากันทุกประการ สามารถหมุนได้ แต่ไม่พลิก / มิร์เรอร์ ตัวอย่างเช่นหากพวกเขาเป็นชิ้นส่วน Tetris พวกเขาจะต้องเหมือนกันคุณไม่สามารถใช้ทั้งชิ้น L และชิ้น J

อินพุต

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

เอาท์พุต

คุณควรพิมพ์เมทริกซ์เดียวกันโดยที่อักขระ '#' แต่ละตัวถูกแทนที่ด้วยตัวเลขตั้งแต่ 0 ถึง n-1 (n คือจำนวนคน) แต่ละหลักควรทำเครื่องหมายเป็นชิ้น รูปร่างชิ้นจะต้องเชื่อมต่อผ่านขอบสี่เหลี่ยม การจัดลำดับหมายเลขไม่จำเป็นต้องเป็นไปตามลำดับใด ๆ หากมีหลายวิธีในการตัดพิซซ่าวิธีใดวิธีหนึ่งก็เป็นที่ยอมรับได้
หากไม่สามารถตัดพิซซ่าได้ตามต้องการคุณควรพิมพ์สตริง "ไม่มีพิซซ่าให้คุณ!" แทน.

เกณฑ์การให้คะแนน

นี่คือรหัสกอล์ฟ คะแนนของคุณจะเป็นจำนวนไบต์ในโปรแกรม ตัวละครจะถูกนับผ่านการเข้ารหัส UTF-8 คะแนนต่ำสุดชนะ

ตัวอย่าง

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

3
 #  
### 
####
   #

เอาท์พุท:

 0  
100 
1122
   2

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

4
###
# #
###

เอาท์พุท:

001
2 1
233

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

2
#    #
######

เอาท์พุท:

No pizza for you!

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

5
    #  
   ####
  #####
 ##### 
#####  
####   
  #    

เอาท์พุท:

    0  
   1000
  21110
 32221 
43332  
4443   
  4    

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

4
   #   
 ####  
###### 
  #####
  #### 

เอาท์พุท:

   0   
 1000  
111203 
  12233
  2233 

ความต้องการ

  • คุณควรเขียนโปรแกรมทั้งหมดที่อ่านจากอินพุตมาตรฐานและเขียนไปยังเอาต์พุตมาตรฐาน
  • โปรแกรมต้องสามารถรันได้ใน Linux โดยใช้ซอฟต์แวร์ที่มีให้ฟรี
  • โปรแกรมของคุณควรทำตัวอย่างด้านบนให้เสร็จในเวลาไม่ถึง 1 นาทีบนคอมพิวเตอร์ที่ทันสมัย
  • ไม่มีช่องโหว่มาตรฐาน

3
กัดที่สิบเก้า: ^)
FryAmTheEggman

@FryAmTheEggman ©งานอดิเรกของ Calvin
aditsu

โบนัสสำหรับโซลูชันของ regex
ข้อบกพร่อง

คำตอบ:


3

รหัส PHP 1808 971 ไบต์

การติดตั้งที่รวดเร็วและสกปรกใน PHP แรงเดรัจฉานแรกบังคับรูปร่างฝานทั้งหมดที่เป็นไปได้ถัดไปบังคับเดรัจฉานตำแหน่งทั้งหมดและการวางแนวของชิ้น

การใช้งาน: cat pizza.txt | php pizza.php

แก้ไข: ลดขนาดรหัสลงมากกว่า 45% โดยอัลกอรึทึม rewring โดยใช้การเรียกซ้ำมากกว่าการวนซ้ำซ้อนกัน อย่างไรก็ตามนี่กินหน่วยความจำ (และของพิซซ่า ;-)) พิซซ่าที่มีขนาดใหญ่กว่า 8x8 อาจจะมีหน่วยความจำไม่เพียงพอ ตัวแปรลูปที่ซ้อนกันสามารถจัดการขนาดใดก็ได้ได้ง่าย แต่มีขนาดเป็นสองเท่าของรหัส

<?php define('A',98);$n=fgets(STDIN);$d=array();$m=$u=str_pad('',A,'+');$s=0;while($g=fgets(STDIN)){$g=rtrim($g);assert(strlen($g)<=A-2);$s++;$m.='+'.str_pad(rtrim($g),A-2,' ').'+';for($l=0;$l<strlen($g);$l++)if($g[$l]=='#')$d[]=$s*A+$l+1;}$m.=$u;$r=count($d)/$n;x(reset($d),array(array()),0,0,0,0);die('No pizza for you!');function x($e,$c,$b,$a,$q,$t){global$r,$m,$d;$h=$a*A+$b;if(!in_array($e+$h,$d))return;if(in_array($h,$c[0]))return;$c[0][]=$h;$c[1][]=$b*A-$a;$c[2][]=-$a*A-$b;$c[3][]=-$b*A+$a;if(count($c[0])<$r)do{x($e,$c,$b+1,$a,$b,$a);x($e,$c,$b,$a+1,$b,$a);x($e,$c,$b-1,$a,$b,$a);x($e,$c,$b,$a-1,$b,$a);$v=($b!=$q||$a!=$t);$b=$q;$a=$t;}while($v);else w($c,$m,0,reset($d),0);}function w(&$p,$f,$o,$e,$i){global$n,$d;foreach($p[$i]as$h){$j=$e+$h;if(!isset($f[$j])||$f[$j]!='#')return;$f[$j]=chr(ord('0')+$o);}if(++$o==$n){for($k=A;$k<strlen($f)-A;$k++)if($k%A==A-1)echo PHP_EOL;else if($k%A)echo$f[$k];exit;}foreach($d as$j)for($i=0;$i<4;$i++)w($p,$f,$o,$j,$i);}

Ungolfed รหัสเอกสาร

ด้านล่างเป็นรหัสต้นฉบับที่เป็นเอกสาร เพื่อรักษาสติของฉันฉันทำงานกับซอร์สโค้ดแบบเต็มและเขียนสคริปต์ minifier ง่าย ๆ ในการตัดคำสั่งเช่นassert()และerror_reporting()ลบวงเล็บเหลี่ยมที่ไม่จำเป็นเปลี่ยนชื่อตัวแปรฟังก์ชั่นและค่าคงที่เพื่อสร้างรหัส golfed ด้านบน

<?php
error_reporting(E_ALL) ;

// Width of each line of pizza shape.
// Constant will be reduced to single character by minifier,
// so the extra cost of the define() will be gained back.
define('WIDTH', 98) ;

// Read number of slices
$nrSlices = fgets(STDIN) ;

// Read pizza shape definition and 
// convert to individual $positionList[]=$y*width+$x and
// linear (1D) $pizzaShape[$y*WIDTH+$x] with protective border around it.
//
// WARNING: assumes maximum pizza width of WIDTH-2 characters!
$positionList = array() ;
$pizzaShape = $headerFooter = str_pad('', WIDTH, '+') ;
$y = 0 ;
while ($line = fgets(STDIN))
{  $line = rtrim($line) ;
   assert(strlen($line) <= WIDTH-2) ;
   $y++ ;
   $pizzaShape .= '+'.str_pad(rtrim($line), WIDTH-2, ' ').'+' ;
   for ($x = 0 ; $x < strlen($line) ; $x++)
   {  if ($line[$x] == '#') $positionList[] = $y*WIDTH + $x+1 ;
   }
}
$pizzaShape .= $headerFooter ;

// Determine size of a slice
$sliceSize = count($positionList)/$nrSlices ;

// Build all possible slice shapes. All shapes start with their first part at 
// the top of the pizza, and "grow" new parts in all directions next to the 
// existing parts. This continues until the slice has the full size. This way
// we end up with all shapes that fit at the top of the pizza.
//
// The shape is defined as the offsets of the parts relative to the base 
// position at the top of the pizza. Offsets are defined as linear offsets in
// the 1-D $pizzaShape string.
//
// For efficiency, we keep track of all four possible rotations while building
// the slice shape.
//
growSlice(reset($positionList), array(array()), 0, 0, 0, 0) ;
die('No pizza for you!') ;

function growSlice($basePosition, $shapeDeltas, $dx, $dy, $prevDx, $prevDy)
{  global $sliceSize, $pizzaShape, $positionList ;

   // Check validity of new position
   // Abort if position is not part of pizza, or 
   // if position is already part of slice
   $delta = $dy*WIDTH + $dx ;
   if (!in_array($basePosition+$delta, $positionList)) return ;
   if (in_array($delta, $shapeDeltas[0])) return ;

   // Add all four rotations to shapeDeltas[]
   $shapeDeltas[0][] = $delta ;
   $shapeDeltas[1][] = $dx*WIDTH - $dy ;
   $shapeDeltas[2][] = -$dy*WIDTH - $dx ;
   $shapeDeltas[3][] = -$dx*WIDTH + $dy ;

   // Have we built a full slice shape?
   if (count($shapeDeltas[0]) < $sliceSize) 
   {  // Grow shape either at current position or at previous position
      do
      {  growSlice($basePosition, $shapeDeltas, $dx+1, $dy,   $dx, $dy) ;
         growSlice($basePosition, $shapeDeltas, $dx,   $dy+1, $dx, $dy) ;
         growSlice($basePosition, $shapeDeltas, $dx-1, $dy,   $dx, $dy) ;
         growSlice($basePosition, $shapeDeltas, $dx,   $dy-1, $dx, $dy) ;
         $retry = ($dx != $prevDx || $dy != $prevDy) ;
         $dx = $prevDx ;
         $dy = $prevDy ;
      } while ($retry) ;
   } else
   {  // Try to cover the entire pizza by translated and rotated instances of
      // the slice shape.
      fitSlice($shapeDeltas, $pizzaShape, 0, reset($positionList), 0) ;
   }
}

function fitSlice(&$shape, $pizza, $id, $basePosition, $rotation)
{  global $nrSlices, $positionList ;

   // Try to fit each part of the slice onto the pizza. If the part falls
   // outsize the pizza, or overlays another slice we reject this position
   // and rotation. If it fits, we mark the $pizza[] with the slice $id.
   foreach ($shape[$rotation] as $delta)
   {  $position = $basePosition + $delta ;
      if (!isset($pizza[$position]) || $pizza[$position] != '#') return ;
      $pizza[$position] = chr(ord('0')+$id) ;
   }

   // If $nrSlices slices have been fitted, we have found a valid solution!
   // In that case, we display the solution and quit.
   if (++$id == $nrSlices)
   {  for ($pos = WIDTH ; $pos < strlen($pizza)-WIDTH ; $pos++)
      {  if ($pos % WIDTH == WIDTH-1) echo PHP_EOL ;
         else if ($pos % WIDTH) echo $pizza[$pos] ;
      }
      exit ;
   }

   // The current slice did fit, but we have still more slices to fit.
   // Try all positions and rotations for the next slice.
   foreach ($positionList as $position)
   {  for ($rotation = 0 ; $rotation < 4 ; $rotation++)
      {  fitSlice($shape, $pizza, $id, $position, $rotation) ;
      }
   }
}

ฉันได้รับ "ข้อผิดพลาดร้ายแรงของ PHP: ไม่สามารถ redeclare _ () ใน pizza.php ที่บรรทัด 1"
aditsu

@aditsu: มีฟังก์ชั่นเดียวเท่านั้น _ () ในเวอร์ชั่น golfed คุณตั้งใจคัดลอกโค้ดสองครั้งหรือไม่?
Jason Smith

ขนาดไฟล์คือ 972 ดังนั้นฉันไม่คิดว่ารหัสจะพอดีสองครั้ง รหัส ungolfed ดูเหมือนว่าจะทำงานครับ :)
aditsu

ฉันสังเกตเห็นว่าคุณมีdefine('_',98)ความขัดแย้งนั้นfunction _ใช่หรือไม่ ฉันไม่รู้ php ดังนั้นฉันจึงบอกไม่ได้ ...
aditsu

@aditsu: โค้ด golfed ใช้งานได้ดีบน Mac ของฉันด้วย PHP 5.4.43 แต่ปรากฏว่า _ () เป็นนามแฝงของ gettext () บนแพลตฟอร์มอื่น ๆ เปลี่ยน minifier เพื่อหลีกเลี่ยง _ () โดยสิ้นเชิง
Jason Smith
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.