Tra parentesi chiaramente i treni APL


19

In APL, puoi scrivere funzioni tacite, chiamate treni . Il modo in cui funzionano è irrilevante per questa sfida. Ecco i diversi modi in cui possono essere raggruppati, usando come funzione:

⍴      -> ⍴
⍴⍴     -> ⍴⍴
⍴⍴⍴    -> ⍴⍴⍴
⍴⍴⍴⍴   -> ⍴(⍴⍴⍴)
⍴⍴⍴⍴⍴  -> ⍴⍴(⍴⍴⍴)
⍴⍴⍴⍴⍴⍴ -> ⍴(⍴⍴(⍴⍴⍴))
...

L'ordine rimane lo stesso. La procedura è che fintanto che ci sono rigorosamente più di 3 funzioni, le ultime 3 funzioni sono raggruppate in una funzione. Se incontriamo un treno annidato, tra parentesi quello prima, per continuare. Ecco la procedura applicata a ⍴⍴⍴⍴⍴⍴:

Step 0: ⍴⍴⍴⍴⍴⍴
There are strictly more than 3 functions, repeat.
Step 1: ⍴⍴⍴(⍴⍴⍴)
There are strictly more than 3 functions, repeat.
Step 2: ⍴(⍴⍴(⍴⍴⍴))
There are 3 or less functions, we're done.

Ecco la stessa procedura applicata a ⍴⍴⍴(⍴⍴)⍴(⍴⍴⍴⍴(⍴⍴⍴))⍴⍴:

Step 0: ⍴⍴⍴(⍴⍴)⍴(⍴⍴⍴⍴(⍴⍴⍴))⍴⍴
There are strictly more than 3 functions, repeat.
We have met a nested train, applying procedure to that first:
  Step 0: ⍴⍴⍴⍴(⍴⍴⍴)
  There are strictly more than 3 functions, repeat.
  We have met a nested train, applying procedure to that first:
    Step 0: ⍴⍴⍴
    There are 3 or less functions, we're done.
  Step 1: ⍴⍴(⍴⍴(⍴⍴⍴))
  There are 3 or less functions, we're done.
Step 1: ⍴⍴⍴(⍴⍴)⍴((⍴⍴(⍴⍴(⍴⍴⍴)))⍴⍴)
There are strictly more than 3 functions, repeat.
We have met a nested train, applying procedure to that first:
  Step 0: ⍴⍴
  There are 3 or less functions, we're done.
Step 2: ⍴⍴⍴((⍴⍴)⍴((⍴⍴(⍴⍴(⍴⍴⍴)))⍴⍴))
There are strictly more than 3 functions, repeat.
Step 3: ⍴(⍴⍴((⍴⍴)⍴((⍴⍴(⍴⍴(⍴⍴⍴)))⍴⍴)))
There are 3 functions or less, we're done.

Ingresso

Per questa sfida, l'input sarà semplificato. Ciò significa che è possibile scegliere 2 caratteri diversi per l'apertura e la chiusura delle parentesi e 1 carattere per le funzioni, diversi da quelli scelti per le parentesi. I caratteri scelti devono essere coerenti. L'input non sarà vuoto e non conterrà parentesi senza contenuto (ad es ().).

Produzione

Ancora una volta, puoi scegliere 3 caratteri diversi, 2 per le parentesi e 1 per le funzioni. Si noti che non devono necessariamente essere uguali a quelli scelti per l'input, ma devono essere coerenti.

Regole

  • Se ci sono parentesi che racchiudono solo una funzione al loro interno nell'input, è necessario rimuoverle nell'output. L'output potrebbe non contenere parentesi non necessarie (ovvero racchiudere una sola funzione o racchiudere l'intero output).
  • Non è necessario implementare l'algoritmo utilizzato qui, purché la soluzione sia valida per questa sfida.
  • Input e output sono stringhe nel formato spiegato nelle sezioni Input e Output. L'input avrà almeno un carattere.
  • L'uso delle scappatoie standard è severamente vietato.
  • Questo è , quindi vince la risposta più breve. Tuttavia, non ci sarà una risposta accettata, poiché si tratta di un concorso per lingua e per incoraggiare la risposta in lingue in cui questo compito comporterebbe un codice più lungo rispetto al codice scritto in altre lingue.

Casi test

I caratteri utilizzati qui sono ()⍴, è necessario sostituirli con i caratteri scelti.

⍴                          -> ⍴
⍴                          -> ⍴
⍴⍴                         -> ⍴⍴
⍴⍴⍴                        -> ⍴⍴⍴
⍴⍴⍴⍴                       -> ⍴(⍴⍴⍴)
⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴            -> ⍴⍴(⍴⍴(⍴⍴(⍴⍴(⍴⍴(⍴⍴(⍴⍴⍴))))))
⍴⍴⍴⍴⍴(⍴⍴⍴)⍴⍴(⍴(⍴⍴⍴)⍴⍴⍴)⍴⍴⍴ -> ⍴(⍴⍴(⍴⍴((⍴⍴⍴)⍴(⍴(⍴(⍴⍴⍴)(⍴⍴⍴))(⍴⍴⍴)))))
(⍴⍴⍴)(⍴⍴⍴)(⍴⍴⍴)            -> (⍴⍴⍴)(⍴⍴⍴)(⍴⍴⍴)
(⍴⍴⍴)(⍴⍴⍴)⍴⍴⍴              -> (⍴⍴⍴)(⍴⍴⍴)(⍴⍴⍴)
⍴⍴(⍴)⍴⍴                    -> ⍴⍴(⍴⍴⍴)
((⍴⍴))                     -> ⍴⍴
⍴⍴((⍴⍴))⍴⍴                 -> ⍴⍴((⍴⍴)⍴⍴)

Questa sfida è stata pubblicata nella Sandbox. Se si dispone del privilegio richiesto, è possibile visualizzare il post sandbox qui .


2
Penso che Fully sia un titolo migliore di Clearly .
Adám,


@Adám Mi aspettavo quella risposta di riferimento, anche se non otterrà molti voti;)
Erik the Outgolfer,

@ Adám La parte chiaramente nel titolo si riferisce al fatto che è necessario rimuovere le parentesi non necessarie. Completamente è qualcosa che dovresti fare quando rispondi a una sfida; p
Erik the Outgolfer,

È vero che questa funzione sarà sempre idempotente?
Esolanging Fruit,

Risposte:


7

APL (Dyalog Classic) , 71 68 65 63 byte

0{⍵≡⍕⍵:⍵⋄⍬≡⍵:'⍬'1=≢⍵:⍺∇⊃⍵⋄3≥≢⍵:⍺⌽')(',⍣⍺∊1∇¨⍵⋄⍺∇¯3(↓,∘⊂1∇↑)⍵}⍎

Provalo online!

I personaggi che ho scelto per I / O sono '(', ')'e '⍬'.

Questa soluzione è essa stessa un treno APL.

analizza l'input come se fosse un array nidificato - un albero con vettori numerici vuoti ( ) come foglie.

Il dfn (cioè lambda - { }) attraversa l'albero in modo ricorsivo e lo converte in una stringa opportunamente tra parentesi. L'argomento sinistro controlla se le parentesi devono essere aggiunte al livello attuale, se necessario.

Il dfn gestisce i seguenti casi in base all'argomento corretto:

  • se è già una stringa ( ⍵≡⍕⍵), restituirla

  • se lo è , restituisci il carattere'⍬'

  • se è un singleton, basta scavare più a fondo ( è il simbolo di una chiamata ricorsiva)

  • se la sua lunghezza è ≤3, ricorrere per ciascuno degli elementi e circondare ()se necessario

  • in caso contrario, ricorrere per la 3-coda, anteporre tutto tranne la 3-coda e ricorrere nuovamente


Sembra 63 caratteri, molti dei quali Unicode. Quale codifica dei caratteri produce 63 byte per questo? Lo faccio 141 byte in UTF8.
Corey,

3
@Corey APL ha una sua tabella codici a 8 bit .
zwol,


@Adám Grazie per quello. Ho cercato ma non sapevo cosa cercare per ottenere quella risposta.
Corey,

3

Python 2 , 224 208 204 byte

-16 byte grazie a Mr. Xcoder -4 byte grazie a ovs

r=str.replace
p='p'
def c(l):
 while len(l)>3:l=l[:-3]+(l[-3:],)
 return l and map(c,l)or l
print r(r(r(r(r(`c(eval(r(r(r(input(),'(p)',p),p,'[],'),')','),')))`,'[]',p),*'[('),*'])'),' ',''),',','')[1:-1]

Provalo online! oppure Prova tutti i casi di test

Il codice può essere diviso in 3 passaggi principali:
conversione dell'input in un elenco nidificato e sostituzione (p)->p. La singola funzione pverrà sostituita da un elenco vuoto.

eval(r(r(r(input(),'(p)',p),p,'[],'),')','),'))

Una funzione ricorsiva per applicare la regola "3 o meno" sull'elenco corrente e chiamarsi su tutti gli elenchi secondari.

def c(l):
 while len(l)>3:l=l[:-3]+(l[-3:],)
 return l and map(c,l)or l

Molte sostituzioni per formattare nel formato di output desiderato

r(r(r(r(r(`c(...)`,'[]',p),*'[('),*'])'),' ',''),',','')[1:-1]


1
Questo non semplifica ((pp))(o p((pp))p).
Martin Ender,

2

CJam , 56 byte

Beats APL!

lW%~]]]{{_,{K_,({~}|}&}%{_,3>}{3/(aa\+:~}w}:K~~`1>W<W%S/

Provalo online!

Funziona (penso) e non ho idea del perché ...

I caratteri di input sono ][Tper ()⍴e i caratteri di output sono ][0per ()⍴(sì, questo significa che sono invertiti da quello che ti aspetteresti; ad esempio, potresti passare TTT]TT[T]TTTT]TTT[[TT).

Panoramica di alto livello

Il programma funziona con l'input all'indietro, perché è più conveniente. Per analizzare l'input, sfruttiamo il parser di CJam: l'inversione e l'esecuzione dell'input forniscono la forma analizzata (all'indietro) dell'input.

Definiamo quindi una procedura K. Kfa la maggior parte del lavoro per la nostra presentazione e funziona come segue:

  • L'array di input sarà un mix di zero e sotto-array non vuoti. Identificare gli array secondari e applicarli Kin modo ricorsivo . Il risultato dovrebbe essere un altro array e se questo array è costituito da un solo elemento, scompattalo (questo eliminerà le parentesi ridondanti).
  • Finché il risultato ha più di tre elementi, raggruppa i suoi primi tre (non i suoi ultimi tre; ricorda che l'input viene elaborato all'indietro) in un unico elenco.
  • Restituisce il risultato.

Applicando Kall'input, otteniamo la forma correttamente tra parentesi dell'input (l'unica cosa da notare è che effettivamente avvolgiamo l'input in un elenco singleton e lo scartiamo in seguito; la ragione di ciò è che vogliamo lo snippet che disimballa i singleton applicare al programma di livello superiore e non solo ai suoi sotto-array). Successivamente, applichiamo solo una formattazione minima per ottenere il nostro risultato.

Qualche spiegazione per i pezzi del golf

Il golf di cui sono più orgoglioso sta usando ,per eseguire il controllo tra numeri interi e array.

  • Se la parte superiore dello stack è un numero intero n , ,genera l'intervallo [0..n) . Poiché l'unico numero intero che incontreremo è 0, questo ci dà sempre l'elenco vuoto [], che è falso.
  • Se la parte superiore dello stack è un array, ,prende la sua lunghezza. Poiché tutte le matrici che incontriamo saranno non vuote, questo ci dà sempre un numero intero positivo, che è vero.

Un altro golf che potrebbe essere di interesse è il metodo che uso per raggruppare i primi tre elementi dell'array; è in qualche modo simile alla mia presentazione "Turing codice dell'interprete linguistico completo" . CJam non ha un modo breve di suddividere un array in due pezzi (puoi provare a tagliare la prima parte e poi l'altra parte mantenendo l'array e l'indice originali nello stack, ma non funziona molto bene) , quindi quello che faccio invece è usare 3/, che raggruppa un array in blocchi di 3. Posso quindi estrarre il primo elemento (, avvolgerlo due volte in array aae quindi ricollegarlo all'inizio dell'elenco \+. Il motivo per cui avvolgiamo due volte l'array è che dobbiamo rimuovere un livello :~, poiché abbiamo anche raggruppato il resto dell'array in sezioni.


Nitpick: questo batte APL senza builtin .
Erik the Outgolfer,

@EriktheOutgolfer Abbastanza giusto.
Esolanging Fruit,

0

JavaScript (ES6), 149 146 byte

i='a';f=s=>s==(s=s[R='replace'](/\((\w+)\)/,(q,t)=>(f[q=i+=0]=f(t),q)))&&s==(s=s[R](/(?!^)((a0+|p){3})$/,"($1)"))?s[R](/a0+/g,t=>`(${f[t]})`):f(s)
<textarea cols=80 id=I>ppp(pp)p(pppp(ppp))pp</textarea><br>
<button onclick=O.innerText=f(I.value)>Run</button><br>
<pre id=O></pre>

Usi ()p, sebbene tu usi una lettera diversa, puoi semplicemente cambiare pverso la fine.

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.