피자를 같은 조각으로 자르십시오


16

이것이 내가이 질문을 생각한 것입니다 내가 완전히 읽기 전에이 이 될 것입니다.

코드 골퍼 그룹이 Nineteenth Bite Pizzeria에 들어가 피자를 주문합니다. 불규칙한 모양으로 제공되며 단위 사각형으로 만들어졌습니다. 당신의 임무는 그들이 동일한 조각으로 잘라 도움이됩니다. 즉, 슬라이스는 모양과 크기가 정확히 같아야합니다. 회전 할 수는 있지만 뒤집거나 미러링 할 수는 없습니다. 예를 들어, 테트리스 조각 인 경우 동일한 종류 여야하며 L 조각과 J 조각을 모두 사용할 수 없습니다.

입력

첫 번째 줄에 그룹의 사람들 수 (항상 2에서 10까지의 정수)와 피자를 나타내는 ''(공백) 및 '#'문자의 직사각형 행렬이 표시됩니다. 모든 '#'문자는 가장자리를 통해 연결됩니다. '#'문자의 수는 여러 사람의 배수 여야합니다.

산출

각 '#'문자를 0에서 n-1까지의 숫자 (n은 사람 수)로 바꾸어 동일한 행렬을 인쇄해야합니다. 각 숫자는 슬라이스를 표시해야합니다. 슬라이스 모양은 사각형 모서리를 통해 연결해야합니다. 슬라이스 번호 매기기는 특정 순서 일 필요는 없습니다. 피자를 자르는 방법이 여러 가지라면 그중 하나를 사용할 수 있습니다.
필요에 따라 피자를자를 수 없다면 "No pizza for you!"라는 문자열을 인쇄해야합니다. 대신에.

채점

이것은 코드 골프입니다. 점수는 프로그램의 바이트 수입니다. 문자는 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 © 캘빈의 취미
아디 츠

정규식 솔루션 보너스.
flawr

답변:


3

PHP 코드 1808 971 바이트

PHP에서 빠르고 더러운 구현. 먼저 모든 가능한 슬라이스 모양을 무차별 대입하고, 다음으로 슬라이스의 모든 위치와 방향을 무차별 대입합니다.

용법: cat pizza.txt | php pizza.php

편집 : 중첩 루프가 아닌 재귀를 사용하여 알고리즘을 다시 작성하여 코드 크기를 45 % 이상 줄였습니다. 그러나 이것은 메모리 (그리고 피자의 ;-)를 먹는다. 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, 문서화 된 코드

아래는 문서화 된 원본 코드입니다. 온전한 정신을 유지하기 위해 전체 소스 코드로 작업하고 and와 같은 문을 제거하고 불필요한 괄호를 제거 assert()하고 error_reporting()변수, 함수 및 상수의 이름을 바꾸어 위의 골프 코드를 생성하는 간단한 축소 기 스크립트를 작성했습니다.

<?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 치명적인 오류 : 재 선언 할 수 없습니다 _ () pizza.php에 1 행의"지고있어
aditsu

@aditsu : 골프 버전에는 _ () 함수가 하나만 있습니다. 실수로 코드를 두 번 복사하여 붙여 넣었습니까?
제이슨 스미스

파일 크기는 972이므로 코드가 두 번 들어갈 수 있다고 생각하지 않습니다. ungolfed 코드는 btw 작동하는 것 같습니다 :)
aditsu

나는 당신이 눈치 define('_',98)에,하지 않은 그 충돌 function _? 내가 말할 수 있도록 나는 ... PHP를 모르는
aditsu

@aditsu : 골프 코드는 PHP 5.4.43이 설치된 Mac에서 제대로 작동하지만 _ ()은 다른 플랫폼의 gettext ()에 대한 별칭입니다. _ ()를 피하기 위해 축소기를 변경했습니다.
Jason Smith
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.