Programmazione delle cipolle


22

Usando solo ASCII stampabile (codici esadecimali da 20 a 7E), scrivi un programma core N × N quadrato senza commenti che è circondato da altri 4 livelli , creando un programma quadrato (N + 8) × (N + 8) (N> 0) . Per N = 3 il layout (da sostituire con il codice effettivo) è simile al seguente:

44444444444
43333333334
43222222234
43211111234
4321CCC1234
4321CCC1234
4321CCC1234
43211111234
43222222234
43333333334
44444444444
  • Le C rappresentano il programma principale 3 × 3.
  • Gli 1 rappresentano il primo strato, i 2 rappresentano il secondo strato, ecc.

Il programma prende sempre una stringa di numeri interi separati da spazio come 0 -1 31 -1 2 2 2via stdin o simili (dovrebbe essere solo i numeri semplici, senza virgolette o parentesi o altro). L'output dipende da quali parti del layout sono state eseguite.

Esistono cinque modi per eseguire il programma (le nuove righe sono incluse nell'esecuzione). Ognuno fa qualcosa di diverso dall'elenco:

  1. Esegui solo il core:

    CCC
    CCC
    CCC
    

    Questo calcola il massimo dei valori assoluti degli elementi dell'elenco di input e lo stampa COREsu una nuova riga più volte. Se il massimo è 0 non viene emesso nulla (una nuova riga va bene).

    • L'output per 0 -1 31 -1 2 2 2sarebbe

      CORE
      CORE
      ...
      

      31 volte.

  2. Esegui il core con il livello 1:

    11111
    1CCC1
    1CCC1
    1CCC1
    11111
    

    Ciò genera la media (media aritmetica ) dei valori di elenco sulla precisione standard in virgola mobile.

    • L'output per 0 -1 31 -1 2 2 2sarebbe 35/7 = 5( 5.0va bene).
  3. Esegui il core con i livelli 1 e 2:

    2222222
    2111112
    21CCC12
    21CCC12
    21CCC12
    2111112
    2222222
    

    Ciò genera un elenco separato da spazi dell'elenco di input invertito.

    • L'output per 0 -1 31 -1 2 2 2sarebbe 2 2 2 -1 31 -1 0.
  4. Esegui il nucleo con i livelli 1, 2 e 3 (il modello dovrebbe essere ovvio).
    Ciò genera un elenco separato da spazi dell'elenco di input ordinato.

    • L'output per 0 -1 31 -1 2 2 2sarebbe -1 -1 0 2 2 2 31.
  5. Esegui il core con i livelli 1, 2, 3 e 4.
    Questo genera un elenco separato da spazi dell'elenco di input con i duplicati rimossi, l'ordinamento non ha importanza.

    • L'output per 0 -1 31 -1 2 2 2potrebbe essere -1 0 2 31.

Tutto l'output è stdout o un'alternativa simile.

Solo queste 5 combinazioni di layout hanno comportamenti specifici.

Gli appunti

  • Non sono consentiti commenti nel nucleo o nei livelli o combinazioni di questi. Il codice che non funziona o non fa nulla di costruttivo non viene considerato come un commento.
  • Ricorda che il nucleo può avere qualsiasi dimensione (positiva) N × N, ma i livelli hanno solo un carattere di spessore.
  • Si può presumere che l'input non abbia spazi iniziali o finali e esattamente uno spazio tra i numeri. Conterrà sempre almeno un numero. (Anche gli elenchi di output devono essere formattati in questo modo.)
  • Si può presumere che l'elenco e i calcoli necessari per l'output non abbiano valori che traboccano (o underflow) i numeri interi (purché il loro massimo sia qualcosa di ragionevole come 2 16 ).

punteggio

Scrivere questo programma normalmente sarebbe facile. Scriverlo con un piccolo core è difficile.

Vince il programma con la dimensione del nucleo più piccola (la N più piccola). In caso di parità, il vincitore è il programma completo (il quadrato (N + 8) × (N + 8)) con il minor numero di caratteri distinti (senza contare le nuove righe).

Si prega di segnalare il valore N nella parte superiore della risposta.


1
Ho pensato che questo sarebbe stato anche un altro di quei nuovi tipi
Optimizer,

Posso usare un linguaggio che ignora tutto dopo una nuova riga?
isaacg,

1
@isaacg Sì (fintanto che newline non è considerato il carattere del commento, il che sarebbe strano).
Calvin's Hobbies,

3
@Optimizer Non tentarmi ... " Ogni risposta aggiunge un nuovo livello al codice cipolla in modo che faccia qualcosa di nuovo con l'elenco ... "
Calvin's Hobbies

1
@Optimizer No. (So che queste regole di I / O sono piuttosto dure ma è per mantenere le cose coerenti in tutte le lingue.)
Calvin's Hobbies

Risposte:


10

CJam, N = 5, 27 (26) caratteri unici

Sono 26 caratteri se non conto gli spazi. Il programma potrebbe effettivamente essere convertito in uno che non utilizza spazi, semplicemente riempiendo tutti gli spazi vuoti con no-ops (ad esempio, _;che duplica l'elemento superiore dello stack e quindi scarta, o ordinando l'array ancora e ancora), ma distrarrebbe semplicemente dal codice reale.

l~]_|S*      
{l~]$S*      
 {l~]W%S*    
  {l~]_,\    
   {l~]{z    
    }%$W=    
    "CORE    
    "*       
         }   
   ;:+d\/ }  
  ;        } 
 ;          }
;            

Provalo qui.

Il nocciolo è

l~]{z
}%$W=
"CORE
"*

(Più una riga vuota.)

Sono abbastanza sicuro che N = 4non si possa fare in CJam (e sono sicuro che Dennis mi convincerà altrimenti: D). Quanto sopra ha 17 caratteri, e mentre potrebbe essere possibile portarlo a 16 (ad esempio se CJam non aveva un bug da soffocare :z, che richiede {z}%, o usando ARGV), non penso che tu possa adattarlo nel layout senza introdurre un'interruzione di riga all'interno CORE.

Tutte le implementazioni sono soluzioni molto semplici per i compiti assegnati. Tutti iniziano con il l~]quale legge STDIN, lo valuta e lo inserisce in un array.

Il livello precedente è sempre circondato {...}, il che lo rende un blocco che non viene eseguito automaticamente. E invece di eseguirlo, l'ho semplicemente scartato dallo stack con ;, quindi nessun livello dipende dal codice nel livello precedente. Nel livello 1, il codice non rientrava nella prima riga, quindi l'ho continuato dopo aver scartato il blocco principale.

Ora per i programmi attuali:

  • Nucleo:

    {z}%$W="CORE
    "*
    

    Mappa abssulla lista, ordinala, prendi l'ultimo elemento, ripeti CORE(e una interruzione di riga) più volte.

  • Strato 1:

    _,\:+d\/
    

    Duplica l'elenco, prendi la lunghezza, scambia gli elementi dello stack, ottieni la somma, esegui il cast double, scambia gli elementi dello stack, dividi. Penso che questo possa essere più breve, ma non ci sono incentivi per farlo.

  • Strato 2:

    W%S*
    

    Invertire l'array, riempire di spazi.

  • Livello 3:

    $S*
    

    Ordinare l'array, sfogliare con spazi.

  • Strato 4:

    Duplica, prendi insieme unione, riffle con spazi.

Sono possibili anche altre ottimizzazioni, come il riutilizzo di ;e *Sdi Layer 2, ma di nuovo, ma non influisce sul punteggio.


17

Python 2 - N = 17, 53 caratteri

Oh, adoro le sfide del layout di origine con Python ...

i=4                     ;
ii=3                    ;
iii=2                   ;
iiii=1                  ;
iiiii=0;R=raw_input     ;
iiiii;w=R().split()     ;
iiiii;n=map(int,w)      ;
iiiii;S=set(n);M=max    ;
iiiii;s=sorted(n)       ;
iiiii;J="\n".join       ;
iiiii;j=" ".join        ;
iiiii;k=M(map(abs,n))   ;
iiiii;A=J(["CORE"]*k)   ;
iiiii;B=sum(n)/len(n)   ;
iiiii;C=j(w[::-1])      ;
iiiii;D=j(map(str,s))   ;
iiiii;E=j(map(str,S))   ;
iiiii;P=A,B,C,D,E       ;
iiiii;print P[i]        ;
iiiii;" /__----__\  "   ;
iiiii;"|/ (')(') \| "   ;
iiii;"  \   __   /  "   ;
iii;"   ,'--__--'.   "  ;
ii;"   /    :|    \   " ;
i;"   (_)   :|   (_)   ";

Tuttavia, c'è ancora spazio bianco inutilizzato.

Potrei ancora migliorare il conteggio dei personaggi unici, ma rimarrò con una migliore leggibilità, se ce ne sono.

Modifica: Oh, è di nuovo Stan !


Probabilmente puoi salvare alcune righe i=*
aliasando

@ M.Herzkamp: Aliasing printnon è possibile con Python 2. Ma certo, probabilmente c'è spazio per miglioramenti - forse usando Python 3.
Falko,

Non conosco Python, ma non manca questo valore assoluto mancante nell'output del codice core -c*max(n)
nutki

@nutki: hai ragione! Non ho letto attentamente. Ma sono stato in grado di risolverlo.
Falko,

6

Python 3: N = 11, 40 caratteri distinti

if 1:              
 if 1:             
  if 1:            
   if 1:           
    p=print;R=0    
    a=input()      
    b=a.split()    
    m=map;a=abs    
    E=max;l=len    
    n=m(int,b);    
    C=['CORE']     
   "R=E(m(a,n))"   
   OO=C*R;s=sum    
   "x='\n'.join"   
   "p(x(O))    "   
  "p(s(n)/l(b)) "  
 "p(*b[::-1])    " 
"p(*sorted(n))    "
p(*set(n))         

Grazie a @Falko per essere la mia musa ispiratrice. Funziona perché Python non crea un nuovo ambito per ciascuna istruzione if, quindi le variabili persistono nelle printistruzioni esterne . Una cosa fastidiosa era che un mapoggetto (nel nostro caso n) può essere usato una sola volta. Quindi è stato necessario stringere la R=E(...)linea, ma Rnon è stato definito. Pertanto sono stato fortunato a lasciare quattro spazi nella prima riga!

L'output può essere risolto fornendo più elementi *b[::-1]anziché l'elenco. L'alternativa ' '.join(...)sarebbe stata troppo lunga.


Bellissimo! Bello vedere un approccio alternativo per gestire gli inizi di linea variabile in Python. Solo alcune brevi dichiarazioni if ​​e tutti quegli spazi vanno bene. :)
Falko,

@Falko: Il rovescio della medaglia è: non c'è spazio per Stan :(
M.Herzkamp

2

C (gcc) , N = 15, 47 caratteri unici

Presuppone sizeof(int) == 4e sizeof(int*) >= sizeof(int).

;                     ;
 ;                   ; 
  ;                 ;  
   ;           float   
    s;c(a,b)int*a,*    
    b;{b=*b-*a;}i,n    
    ,*f;*q,*R,C,E ;    
    main(a){for(;0<    
    scanf("%i",&a);    
    i=i<abs(a)?a:i,    
    s+=f[n-!0]=a)f=    
    realloc(f,++n*4    
    );qsort(f,n*C,4    
    ,c);for(i=q?R?n    
    :!0:i;i--;a=f[i    
    ])!E|n-i<2|a!=f    
    [i]&&printf(q?R    
    ?R:q:"CORE\n",!    
    q+R?f[i]:s/n);}    
   ;*q="%f";       ;   
  ;*R="%.0f ";      ;  
 ;C=!0;              ; 
;E=!0;                ;

4 strati

3 strati

2 strati

1 strato

Nucleo


0

Incantesimi runici , N = 9 N = 8, 38 personaggi

/ o/\  \     \S\
" //RiU\      \}
@            q "
"        }+1\r @
}   ^U \    {q "
     \{\?)}\+  }
  o\/'|A:{:/R' S
 //r/Ril2=?\?R :
   ,A~/"OC"/=? {
   @| \"RE"\3= =
 D$\' /rqka/l2S?
    i \*@   il\/
   'R1i     Ui ~
 R$/Rak      U \
 ?!D  Rlril1-{=
R   R: }S:{=?\~

Provalo online!

Ho scoperto che mi sbagliavo , ho dimenticato di avere già un ocomando esplicito a causa di un problema con "ordina un elenco" in precedenza. Ciò, tuttavia, limita la dimensione degli input che il programma finale può assumere (8 valori) a causa dei costi interni del comando di ordinamento. Una leggera modifica può aumentare la dimensione di input a 13 al costo di 1 carattere unico o a 19 per due caratteri unici (tutti i caratteri aggiuntivi sono sul livello 1 e aggiunti contemporaneamente, ma la capacità aumentata dello stack dell'IP non è necessario fino al Livello 3, in quanto C, L1 e L2 possono eseguire i loro calcoli senza contenere l'intero input in memoria).

Core: provalo online!

Livello 1: provalo online!

Livello 2: provalo online!

Livello 3: provalo online!

Livello 4: provalo online!

Un'ulteriore compressione è altamente improbabile, a causa dello spazio ridotto che richiede un aumento del numero di caratteri di controllo del flusso. Ho trovato un arrangiamento che ha dato 9 spazi vuoti nel programma principale, ma ciò non è sufficiente, come abbiamo bisogno (un arrangiamento corretto) 15.

Spiegare come uno di questi programmi funzioni è difficile senza una mappa visiva del percorso seguito dall'IP, che è ingombrante e richiede tempo per essere costruito. Il punto di ingresso iniziale è l'angolo in alto a sinistra del programma Core ( ^) che consente un controllo costante del flusso quando vengono aggiunti nuovi livelli, poiché ogni livello ha l'opportunità di intercettare sulla linea appena aggiunta in alto o in basso.

I livelli 1 e 2 intercettano nella parte inferiore (in modo che la linea superiore rimanga vuota per i livelli futuri) e quindi eseguano le loro operazioni lungo il bordo destro (un anello disposto verticalmente). Il livello 1 è leggermente troppo lungo e occupa anche 3 caratteri lungo il bordo superiore, ma il riflettore diagonale ( \) in alto a destra riallinea l'IP con l'iterazione del ciclo successivo.

Il livello 3 intercetta lungo il bordo superiore per afferrare il primo valore di input prima di reindirizzare al bordo inferiore (il livello 4 lascia un NOP in questa colonna nella sua riga inferiore) e legge l'input completo usando il loop del bordo inferiore, reindirizzando verso il basso command ( D) in basso a sinistra. Da lì l'IP rimbalza alcune volte prima di finire in un $loop output ( ) in basso a sinistra per separare i valori nello spazio.

Il livello 4 utilizza tutte le funzionalità del livello 3 (quindi lo spazio vuoto), ma intercetta sul proprio nuovo bordo superiore (in alto a sinistra) per eseguire la propria funzionalità al termine dell'elaborazione del livello 3. L'angolo in alto a sinistra inserisce una stringa "@"che viene utilizzata per indicare la fine dell'array prima di entrare nel ciclo di elaborazione nella parte inferiore. Se viene trovato un valore duplicato, viene visualizzato ( ~angolo in basso a destra), altrimenti viene utilizzato il ramo che consuma il nuovo bordo destro. Questo ramo laterale controlla se è stata raggiunta la fine dell'array e, in tal caso, esplode e si dirige verso lo stesso loop di output separato dallo spazio dal livello 3. In caso contrario, utilizzare lo spazio vuoto sul livello 3 per tornare al principale ciclo continuo.

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.