Taglia una pizza a fette identiche


16

Questo è quello che pensavo fosse questa domanda , prima di leggerla appieno.

Un gruppo di giocatori di golf di codice entra nella The Nineteenth Bite Pizzeria e ordina una pizza. Ha una forma irregolare, fatta di quadrati unitari. Il tuo compito è di aiutarli a tagliarlo in fette identiche. Cioè, le sezioni devono avere la stessa identica forma e dimensione; possono essere ruotati ma non capovolti / specchiati. Ad esempio, se sono pezzi di Tetris, devono essere dello stesso tipo, non puoi usare sia un pezzo a L che un pezzo a J.

Ingresso

Ti verrà dato il numero di persone nel gruppo sulla prima riga (sempre un numero intero compreso tra 2 e 10, incluso), seguito da una matrice rettangolare di caratteri '' (spazio) e '#', che rappresentano la pizza. Tutti i caratteri "#" sono collegati attraverso i loro bordi. Il numero di caratteri '#' è garantito per essere un multiplo del numero di persone.

Produzione

Dovresti stampare la stessa matrice, con ogni carattere '#' sostituito con una cifra da 0 a n-1 (n è il numero di persone). Ogni cifra dovrebbe segnare una fetta. La forma della fetta deve essere collegata attraverso i bordi quadrati. La numerazione delle sezioni non deve essere in alcun ordine particolare. Se ci sono diversi modi per tagliare la pizza, uno di questi è accettabile.
Se non è possibile tagliare la pizza come richiesto, è necessario stampare la stringa "No pizza for you!" anziché.

punteggio

Questo è il codice golf. Il tuo punteggio sarà il numero di byte nel programma. I personaggi verranno conteggiati attraverso la loro codifica UTF-8. Il punteggio più basso vince.

Esempi

Ingresso:

3
 #  
### 
####
   #

Produzione:

 0  
100 
1122
   2

Ingresso:

4
###
# #
###

Produzione:

001
2 1
233

Ingresso:

2
#    #
######

Produzione:

No pizza for you!

Ingresso:

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

Produzione:

    0  
   1000
  21110
 32221 
43332  
4443   
  4    

Ingresso:

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

Produzione:

   0   
 1000  
111203 
  12233
  2233 

Requisiti

  • È necessario scrivere un programma completo che legge dallo standard input e scrive sullo standard output.
  • Il programma deve essere eseguibile su Linux utilizzando software disponibile gratuitamente.
  • Il tuo programma dovrebbe completare ciascuno degli esempi sopra in meno di 1 minuto su un computer moderno.
  • Nessuna scappatoia standard.

3
The Nineteenth Bite : ^)
FryAmTheEggman

@FryAmTheEggman © Calvin's Hobbies
aditsu,

Bonus per soluzioni regex.
Flawr,

Risposte:


3

Codice PHP, 1808 971 byte

Implementazione rapida e sporca in PHP. Prima forza bruta tutte le possibili forme di fetta, successiva forza bruta tutte le posizioni e gli orientamenti delle fette.

Uso: cat pizza.txt | php pizza.php

Modifica: dimensioni del codice ridotte di oltre il 45% tramite il rewring dell'algoritmo mediante ricorsione piuttosto che loop nidificati. Tuttavia, questo mangia memoria (e pizza ;-)). La pizza più grande di 8x8 probabilmente esaurirà la memoria. La variante del ciclo nidificato può gestire facilmente qualsiasi dimensione, ma è il doppio della dimensione del codice.

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

Codice non archiviato e documentato

Di seguito è riportato il codice originale documentato. Per mantenere la sanità mentale, ho lavorato con il codice sorgente completo e ho scritto un semplice script di minificatore per rimuovere istruzioni come assert()e error_reporting(), rimuovere parentesi non necessarie, rinominare variabili, funzioni e costanti per generare il codice golf sopra.

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

Viene visualizzato il messaggio "Errore irreversibile PHP: Impossibile ripetere _ () in pizza.php sulla riga 1"
aditsu,

@aditsu: esiste solo una funzione _ () nella versione golf. Hai accidentalmente copiato e incollato il codice due volte?
Jason Smith,

La dimensione del file è 972, quindi non credo che il codice potrebbe adattarsi due volte. Il codice ungolf sembra funzionare tra l'altro :)
aditsu,

Ho notato che hai define('_',98), non è in conflitto con function _? Non conosco php quindi non posso dirlo ...
aditsu,

@aditsu: il codice di golf funziona bene sul mio Mac con PHP 5.4.43, ma sembra che _ () sia un alias per gettext () su altre piattaforme. Modificatore modificato per evitare del tutto _ ().
Jason Smith,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.