Decodifica il Vuoto


25

Un elenco vuoto è un elenco che a nessun livello contiene oggetti non di elenco. O se preferisci una definizione ricorsiva

  • L'elenco vuoto è nullo

  • Un elenco contenente solo altri elenchi vuoti è nullo

Tutti gli elenchi di vuoti hanno una profondità finita.

Ecco alcuni esempi di liste vuote (usando la sintassi di Python):

[]
[[]]
[[],[]]
[[[]]]
[[[]],[]]
[[],[[]]]

Ecco alcuni esempi di cose che non sono liste vuote:

["a"]
[[...]]
[1]
2
[[],([],[])]

Compito

Scrivi due funzioni separate (o programmi se preferisci). Uno dovrebbe prendere un numero intero positivo (puoi anche includere zero se lo desideri) come argomento e restituire un elenco vuoto, l'altro dovrebbe prendere un elenco vuoto e restituirlo un numero intero. Queste due funzioni dovrebbero essere sempre inverse l'una rispetto all'altra. Cioè se si passa l'output di fin gsi dovrebbe ottenere l'input originale di fcome risultato di g. Ciò significa che la mappatura deve essere 1: 1, ovvero per ogni numero intero, può esistere esattamente un solo elenco vuoto per il quale gfornisce quel numero intero e per ogni elenco vuoto deve esserci esattamente un numero intero per il quale fdà tale elenco vuoto.

Stai essenzialmente creando una Bijection

È possibile scegliere di utilizzare una rappresentazione in formato stringa di un elenco vuoto (con o senza virgole e spazi) anziché il tipo di elenco nativo delle lingue.

punteggio

Il tuo punteggio sarà la lunghezza delle due funzioni insieme. Questo è quindi dovresti mirare a minimizzare questa somma.



1
Questa domanda richiede due funzioni mentre il duplicato richiede solo la prima metà.
Ian Miller,

3
Ratti. Ho quasi pubblicato la risposta migliore che avevo ancora scritto, e non si qualifica per l'altra sfida.
Caleb Kleveter,

2
@IanMiller Direi che l'altra sfida ha diverse linee guida per la codifica rispetto a questa.
Caleb Kleveter,

1
Forse avrebbe più senso che questa domanda fosse solo il decodificatore? Perché c'è già una domanda sull'encoder.

Risposte:


7

Pyth, 27 + 29 = 56 byte

f:

L?bol`NS{sm[d+d]Y]d)ytb]Y@y

Suite di test

g:

L?bol`NS{sm[d+d]Y]d)ytb]Yxyl`

Suite di test

Il sistema è molto semplice: ho generato tutti gli elenchi possibili con non più di un certo numero di [. Quindi, li ordino in modo tale che gli elenchi che non ho ancora generato siano vicini alla fine. Questo è tutto fatto dalla funzione y, identica in entrambi i programmi. È scritto come

L?bol`NS{sm[d+d]Y]d)ytb]Y

Quindi, indicizzo in questo elenco fe lo cerco g.

Il numero di elenchi che ho generato è stato scelto per essere abbastanza grande da aver generato tutti gli elenchi possibili che sarebbero apparsi nella posizione desiderata o prima dell'elenco infinito.

I programmi consentono / restituiscono 0 come opzione.


5

Python 2 , 96 byte

Provalo online! per testare la biiezione.

f=lambda l:len(l)and f(l[0])*2+1<<f(l[1:])

Porta gli elenchi vuoti a numeri interi non negativi. 42 byte.

g=lambda n:n*[g]and[g(n/(n&-n)/2)]+g(len(bin(n&-n))-3)

Porta gli interi non negativi agli elenchi vuoti. 54 byte. Un tentativo più ricorsivo ha dato la stessa lunghezza.

g=lambda n,i=0:n*[g]and[g(n/2,i+1),[g(n/2)]+g(i)][n%2]

1

Java 7, 725 byte

f(int)( 325 byte ):

String f(int i){String s="";for(int j=0,e=0;e<i;e+=v(s))s=Integer.toBinaryString(j++);return"["+s.replace("1","[").replace("0","]")+"]";}int v(String s){for(;!s.isEmpty();s=s.replaceFirst("1","").replaceFirst("0",""))if(s.replace("1","").length()!=s.replace("0","").length()|s.charAt(0)<49|s.endsWith("1"))return 0;return 1;}

g(String)( 75 + 325 byte ):

int g(String s){int r=0;for(String i="10";!i.equals(s);i=f(++r));return r;}

Poiché il metodo gutilizza il metodo fper calcolare il risultato eseguendo il ciclo su un possibile elenco vuoto fino a quando non trova quello uguale a quello immesso, i byte di fvengono conteggiati due volte (poiché entrambi i metodi dovrebbero essere in grado di funzionare senza l'altro per questa sfida).

Spiegazione:

In generale, il metodo fesegue semplicemente il ciclo su tutte le rappresentazioni binarie di stringhe di numeri interi e aumenta un contatore ogni volta che ne viene trovato uno valido. Le stringhe binarie valide per questa sfida sono conformi alle seguenti regole: iniziano con a 1e finiscono con a 0; hanno un numero uguale di 1 e 0; e ogni volta che rimuovi il primo 1e 0convalidi ciò che resta, queste due regole si applicano comunque. Dopo che il contatore è uguale all'input, converte quella stringa binaria in una lista vuota stringa, sostituendo tutto 1con [e tutto 0con ].

Per quanto riguarda il metodo g: iniziamo con "[]"(che rappresenta l'elenco vuoto 0), quindi continuiamo a utilizzare il metodo faumentando un numero intero, finché non corrisponde alla stringa di input.

String f(int i){         // Method `f` with integer parameter and String return-type
  String s="";           //  Start with an empty String
  for(int j=0,e=0;e<i;   //  Loop as long as `e` does not equal the input
      e+=v(s))           //    And append increase integer `e` if String `s` is valid
    s=Integer.toBinaryString(j++);
                         //   Change `s` to the next byte-String of integer `j`
                         //  End of loop (implicit / single-line body)
  return"["+             //  Return the result String encapsulated in "[" and "]"
    s.replace("1","[").replace("0","]")+"]";
                         //  after we've replaced all 1s with "[" and all 0s with "]"
}                        // End of method `f`

int v(String s){         // Separate method with String parameter and integer return-type
  for(;!s.isEmpty();     //  Loop as long as String `s` isn't empty
      s=s.replaceFirst("1","").replaceFirst("0",""))
                         //    After each iteration: Remove the first "1" and "0"
    if(s.replace("1","").length()!=s.replace("0","").length()
                         //   If there isn't an equal amount of 1s and 0s
       |s.charAt(0)<49   //   or the String doesn't start with a 1
       |s.endsWith("1")) //   or the String doesn't end with a 0
      return 0;          //    Return 0 (String is not valid)
                         //  End of loop (implicit / single-line body)
  return 1;              //  Return 1 (String is valid)
}                        // End of separate method

int g(String s){         // Method `g` with String parameter and integer return-type
  int r=0;               // Result integer
  for(String i="[]";!i.equals(s);
                         //  Loop as long as `i` does not equal the input String
      i=f(++r));         //   After each iteration: Set `i` to the next String in line
  return r;              //  Return the result integer
}                        // End of method `g`

Esempi di casi di input e output:

Provalo qui. (NOTA: è piuttosto lento per gli ultimi casi di test. Ci vorranno circa 10-15 secondi per tutti.)

0   <-> []
1   <-> [[]]
2   <-> [[][]]
3   <-> [[[]]]
4   <-> [[][][]]
5   <-> [[][[]]]
6   <-> [[[]][]]
7   <-> [[[][]]]
8   <-> [[[[]]]]
9   <-> [[][][][]]
10  <-> [[][][[]]]
11  <-> [[][[]][]]
12  <-> [[][[][]]]
13  <-> [[][[[]]]]
14  <-> [[[]][][]]
50  <-> [[[][[[]]]]]
383 <-> [[[][]][[[][]]]]

1
Non penso che [][]sia un elenco. Forse sto fraintendendo il modo in cui Java fa qualunque cosa. Aggiungendoli [...]tutti intorno e avendo 0 map to []dovrebbe fare il trucco.
Wheat Wizard

@WheatWizard Ah, buona chiamata. Proverò a risolvere questo problema. Non avevo ancora abbastanza byte, comunque. ; P
Kevin Cruijssen,

@WheatWizard Ok, ora dovrebbe essere risolto. Sfida dura ma divertente tra l'altro. Ci è voluto un po 'prima che capissi cosa volevi dire, e ancora di più per scrivere questa risposta, ma è stato divertente. :)
Kevin Cruijssen,



0

Python 3 - segno / abs, 73 byte

f=lambda n:[[[]]*(n<0),[[]]*abs(n)]
g=lambda l:[-1,1][not l[0]]*len(l[1])

Provalo online!

Implementazione diretta, supporta numeri negativi.

Il numero intero iè codificato [sign(i), abs(i)], dove sign(i)=[] if i > 0 else [[]]e abs(i)=[[]] * i, cioè un elenco di elenchi vuoti con lunghezza abs (i).

Python 3 - binario, 126 byte

Questa è una versione più elaborata (e molto più lunga ...), in cui il valore assoluto è codificato in una rappresentazione di elenco binario.

f=lambda n:[[[]]*(n<0),[[[]]*int(i)for i in f"{n:+b}"[1:]]]
g=lambda l:[-1,1][not l[0]]*int(''.join(map(str,map(len,l[1]))),2)

Provalo online!


1
Non funziona per elenchi di vuoti più complessi: provalo online!
Jitse il

Ah, in qualche modo mi mancava, che ci dovrebbe essere una mappatura per ogni elenco vuoto ... hai ragione.
movatica,

0

Stax , 33 byte totali

Questi programmi sono inversi l'uno dall'altro. Si convertono da e verso tutte le liste vuote e tutti i numeri interi non negativi, quindi include 0. Sembra che sia forse una funzione famosa di un qualche tipo di algebra che non conosco. Per avvolgerci la testa, ho prima implementato i programmi come funzioni in Python.

def convert_to_void(n):
    lst = []
    while n > 0:
        n -= 1
        choices = len(lst) + 1
        choice = n % choices
        cutpoint = len(lst) - choice
        n //= choices
        newgroup = lst[cutpoint:]
        del lst[cutpoint:]
        lst.append(newgroup)
    return lst

def convert_from_void(lst):
    n = 0
    while lst != []:
        newgroup = lst.pop()
        n *= len(lst) + len(newgroup) + 1
        n += len(newgroup) + 1
        lst.extend(newgroup)
    return n

I programmi stax hanno lo stesso comportamento.

Numero intero non negativo → Elenco vuoto, 15 byte

ƒâ₧~└3BI─¿-rÅ;ì

Esegui ed esegui il debug

Elenco vuoto → Numero intero non negativo, 18 byte

Çäê[!σ`c↑Ö§░NR╥ç=Æ

Esegui ed esegui il debug

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.