Cắt pizza thành những lát giống hệt nhau


16

Đây là những gì tôi nghĩ câu hỏi này sẽ có, trước khi tôi đọc nó đầy đủ.

Một nhóm những người chơi gôn mã bước vào The Nineteenth Bite Pizzeria và đặt một chiếc bánh pizza. Nó có hình dạng bất thường, được làm bằng các ô vuông đơn vị. Nhiệm vụ của bạn là giúp họ cắt nó thành những lát giống hệt nhau. Đó là, các lát phải có hình dạng và kích thước chính xác; chúng có thể được xoay nhưng không được lật / nhân đôi. Ví dụ: nếu chúng là các mảnh Tetris, chúng phải cùng loại, bạn không thể sử dụng cả mảnh L và mảnh J.

Đầu vào

Bạn sẽ được cung cấp số người trong nhóm trên dòng đầu tiên (luôn bao gồm một số nguyên từ 2 đến 10, bao gồm), theo sau là một ma trận hình chữ nhật gồm các ký tự '' (dấu cách) và '#', đại diện cho pizza. Tất cả các ký tự '#' được kết nối thông qua các cạnh của chúng. Số lượng ký tự '#' được đảm bảo là bội số của số người.

Đầu ra

Bạn nên in cùng một ma trận, với mỗi ký tự '#' được thay thế bằng một chữ số từ 0 đến n-1 (n là số người). Mỗi chữ số nên đánh dấu một lát. Hình dạng lát phải được kết nối thông qua các cạnh vuông. Việc đánh số lát không cần theo bất kỳ thứ tự cụ thể nào. Nếu có nhiều cách cắt bánh pizza, bất kỳ trong số chúng đều được chấp nhận.
Nếu không thể cắt pizza theo yêu cầu, bạn nên in chuỗi "Không có pizza cho bạn!" thay thế.

Chấm điểm

Đây là mã golf. Điểm của bạn sẽ là số byte trong chương trình. Các ký tự sẽ được tính thông qua mã hóa UTF-8 của chúng. Điểm số thấp nhất chiến thắng.

Ví dụ

Đầu vào:

3
 #  
### 
####
   #

Đầu ra:

 0  
100 
1122
   2

Đầu vào:

4
###
# #
###

Đầu ra:

001
2 1
233

Đầu vào:

2
#    #
######

Đầu ra:

No pizza for you!

Đầu vào:

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

Đầu ra:

    0  
   1000
  21110
 32221 
43332  
4443   
  4    

Đầu vào:

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

Đầu ra:

   0   
 1000  
111203 
  12233
  2233 

Yêu cầu

  • Bạn nên viết một chương trình đầy đủ đọc từ đầu vào tiêu chuẩn và ghi vào đầu ra tiêu chuẩn.
  • Chương trình phải được chạy trong Linux bằng phần mềm có sẵn miễn phí.
  • Chương trình của bạn sẽ hoàn thành từng ví dụ trên trong chưa đầy 1 phút trên máy tính hiện đại.
  • Không có sơ hở tiêu chuẩn.

3
Cắn thứ mười chín : ^)
FryAmTheEggman

@FryAmTheEggman © Sở thích của Calvin
aditsu

Tiền thưởng cho các giải pháp regex.
flawr

Câu trả lời:


3

Mã PHP, 1808 971 byte

Thực hiện nhanh và bẩn trong PHP. Lực lượng vũ phu đầu tiên tất cả các hình dạng lát cắt có thể, lực lượng vũ phu tiếp theo tất cả các vị trí và hướng của các lát cắt.

Sử dụng: cat pizza.txt | php pizza.php

Chỉnh sửa: giảm kích thước mã hơn 45% bằng cách viết lại thuật toán bằng cách sử dụng đệ quy thay vì các vòng lặp lồng nhau. Tuy nhiên, điều này ăn bộ nhớ (và pizza ;-)). Pizza lớn hơn 8x8 có thể sẽ hết bộ nhớ. Biến thể vòng lặp lồng nhau có thể dễ dàng xử lý bất kỳ kích thước nào, nhưng gấp đôi kích thước mã.

<?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, mã tài liệu

Dưới đây là tài liệu, mã gốc. Để giữ sự tỉnh táo của mình, tôi đã làm việc với mã nguồn đầy đủ và viết một tập lệnh khai thác đơn giản để loại bỏ các câu lệnh như assert()error_reporting(), loại bỏ các dấu ngoặc không cần thiết, đổi tên các biến, hàm và hằng số để tạo mã golf ở trên.

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

Tôi đang nhận được "Lỗi nghiêm trọng của PHP: Không thể redeclare _ () trong pizza.php trên dòng 1"
aditsu

@aditsu: chỉ có một chức năng _ () trong phiên bản chơi gôn. Bạn đã vô tình sao chép-dán mã hai lần?
Jason Smith

Kích thước tệp là 972 vì vậy tôi không nghĩ mã có thể vừa hai lần. Mã không mã hóa dường như hoạt động btw :)
aditsu

Tôi nhận thấy bạn có define('_',98), không xung đột với function _? Tôi không biết php nên tôi không thể nói ...
aditsu

@aditsu: Mã golf hoạt động tốt trên máy Mac của tôi với PHP 5.4.43, nhưng nó xuất hiện _ () là bí danh cho gettext () trên các nền tảng khác. Thay đổi công cụ khai thác để tránh _ () hoàn toàn.
Jason Smith
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.