Programma di aggiornamento dei file di lingua di Minecraft


11

In 1.13, i file di lingua di Minecraft sono passati da un semplice formato multi-line key = value a JSON .

Sfida

Scrivi un programma che converte dal formato originale restituendo una stringa JSON. L'input può essere preso usando qualsiasi metodo di input standard, l'output deve essere json da qualsiasi metodo di output standard

Il formato originale contiene righe con coppie chiave = valore, ad esempio

tile.dirt.name=Dirt
advMode.nearestPlayer=Use "@p" to target nearest player

build.tooHigh=Height limit for building is %s blocks

Dovrebbe essere convertito in un oggetto JSON di grandi dimensioni con key = value

{
    "tile.dirt.name": "Dirt",
    "advMode.nearestPlayer": "Use \"@p\" to target nearest player",
    "build.tooHigh": "Height limit for building is %s blocks"
}

Alcuni dettagli

  • È consentito qualsiasi JSON valido purché contenga solo le coppie chiave / valore corrette. Le virgole finali sono consentite perché Minecraft le consente.
  • Le uniche cose che devono essere evitate sono le virgolette. (Nel file di lingua precedente alla 1.13 non esistevano newline, barre rovesciate o altre cose rompiscatole)
  • Le righe vuote devono essere ignorate
  • Le linee contengono esattamente uno uguale

Casi test

Ingresso:

tile.dirt.name=Dirt
advMode.nearestPlayer=Use "@p" to target nearest player

build.tooHigh=Height limit for building is %s blocks

Produzione:

{
    "tile.dirt.name": "Dirt",
    "advMode.nearestPlayer": "Use \"@p\" to target nearest player",
    "build.tooHigh": "Height limit for building is %s blocks"
}

Ingresso:

translation.test.none=Hello, world!
translation.test.complex=Prefix, %s%2$s again %s and %1$s lastly %s and also %1$s again!
translation.test.escape=%%s %%%s %%%%s %%%%%s
translation.test.invalid=hi %
translation.test.invalid2=hi %  s
translation.test.args=%s %s
translation.test.world=world

Produzione:

{
  "translation.test.none": "Hello, world!",
  "translation.test.complex": "Prefix, %s%2$s again %s and %1$s lastly %s and also %1$s again!",
  "translation.test.escape": "%%s %%%s %%%%s %%%%%s",
  "translation.test.invalid": "hi %",
  "translation.test.invalid2": "hi %  s",
  "translation.test.args": "%s %s",
  "translation.test.world": "world",
}

Ingresso:

stat.mineBlock=%1$s Mined
stat.craftItem=%1$s Crafted
stat.useItem=%1$s Used
stat.breakItem=%1$s Depleted

Produzione:

{
    "stat.mineBlock": "%1$s Mined",
    "stat.craftItem": "%1$s Crafted",
    "stat.useItem": "%1$s Used",
    "stat.breakItem": "%1$s Depleted"
}

1
Come tile.dirt.namediventa "block.minecraft.dirt"?
Pavel

@Pavel uuh ... whoops. Risolto questo. Non era intenzionale
pfg

5
È garantito che ogni riga non vuota contenga esattamente 1 =?
user202729

@utente202729 sì
pfg

3
Sarei disposto a scommettere che in realtà hai bisogno di una soluzione a questo problema e intendo usarne uno per convertire i tuoi file. :)
mbomb007

Risposte:


4

Python 3, 91 77 byte

-14 byte grazie a OMᗺ

Ho pensato che la stampa di un dizionario Python sarebbe abbastanza vicina a JSON da renderlo un linguaggio molto competitivo per questa sfida. Tuttavia, la rappresentazione in formato stringa dei dizionari Python è abbastanza diversa da JSON che ho avuto più fortuna nell'usare la libreria JSON integrata di Python. Scommetto che questo può essere fatto più succintamente in JavaScript.

import json
f=lambda x:json.dumps(dict(i.split("=")for i in x.split("\n")if i))

Provalo online!


Modificare:

Bash + Sed, 68 63 byte

Bug risolto grazie a OMᗺ e Night 2
-5 Byte grazie a OMᗺ

Mi sono reso conto che potrebbe essere più efficiente il byte convertire direttamente il testo in JSON senza raggrupparlo in un oggetto, così come il mio approccio per la soluzione Python. Per byte, sed è il linguaggio più potente per la sostituzione di regex che conosco.

echo {`echo "$1"|sed 's/"/\\\"/g;s/\(.*\)=\(.*\)/"\1":"\2",/'`}

Provalo online!

Spiegazione

echo {`                                  #  prints the leading curly brace
       echo "$1"|sed                     # feeds the input into sed
       's/"/\\"/g;                       # replaces " with \"
       s/\(.*\)=\(.*\)/"\1":"\2",/'      # surrounds the left and right hand sides of the equals with quotes and joins them with a colon
`}                                       # prints the closing curly brace

8
Se stai rispondendo in due lingue diverse, sentiti libero di postarlo come due risposte separate.
mbomb007,

Per la risposta bash + sed, prova a usare il -rflag per sed (+3 byte) in modo da non dover sfuggire ai gruppi di acquisizione (-4 byte) tio.run/##LYq7CgIxEEX7/…
user41805

4

Vim, 44 byte

O{<Esc>:%s/"/\\"/g|%s/\v(.*)\=(.*)/"\1":"\2",
o}

Spiegazione:

O{<Esc>                                           Prepend {
       :%s/"/\\"/g                                Escape all "
                  |%s/\v(.*)\=(.*)/"\1":"\2",     Json-ify lines
o}                                                Append }

3

Ruggine , 150 byte

|s:String|s.replace('"',"\\\"").split('\n').filter(|l|l.len()>0).map(|l|format!("\"")+&l.replace('=',"\":\"")+"\",").fold(format!("{{"),|r,n|r+&n)+"}"

Provalo online!

È più lungo di Java?


2

Retina 0.8.2 , 35 byte

"
\"
=
": "
G`.
.+
    "$&",
^
{¶
$
¶}

Provalo online! Sarebbe 34 byte in Retina 1 come è possibile utilizzare al L$`.+posto di G`.e .+. Spiegazione:

"
\"

Sfuggire alle virgolette.

=
": "

Correggi il separatore chiave / valore. (Se il valore può contenere a =, utilizzare 1`=ad un costo di 2 byte.)

G`.

Rimuovi le righe vuote.

.+
    "$&",

Avvolgi ogni riga tra virgolette. (Le citazioni interne sono state aggiunte in precedenza.)

^
{¶
$
¶}

Avvolgere l'intero output in {}s.


2

Buccia , 22 byte

La manipolazione delle stringhe non è davvero la forza di Husk, ma ha funzionato abbastanza bene:

`J"{}"J',mȯJ':msx'=fI¶

Provalo online!

                      ¶  -- split on newlines
                    fI   -- filter by identity (ie. remove empty strings)
         m(        )     -- with each line
                x'=      -- | split on '='
              ms         -- | show each (ie. enclose in quotes and escape quotes)
           J':           -- | join with ':'
      J',                -- join these with ','
`J"{}"                   -- join the string "{}" with the result

Ironia della sorte, c'è qualcosa chiamato "Husk" in Minecraft!
Programmi Redwolf,

2

Rubino , 56 byte

->x{x.split(?\n).map{|i|i.split(?=)}.to_h.to_json}

+6 byte per -rjsonflag interprete.

Provalo online!


1
@Piccolo hai superato la bandiera -rjson?
pag

@pfg Wow, ho davvero lasciato cadere la palla su quell'haha. Non solo avevo dimenticato di usare -rjson, ma avevo anche ipotizzato senza verificare effettivamente che l'errore fosse lo stesso che avevo coinvolto in precedenzato_h
Piccolo

2

Perl 5 -nl -M5.010 , 58 54 byte

BEGIN{say'{'}s'"'\"'g;/=/&&say qq|"$`": "$'",|}{say'}'

Provalo online!


Versione a 58 byte:

BEGIN{say'{'}s'"'\"'g;s/(.*)=(.*)/"$1": "$2",/;END{say'}'}

Provalo online!


Entrambe le versioni aggiungono una virgola dopo ogni chiave: coppia di valori, che non è tecnicamente conforme a JSON (la virgola finale prima della chiusura }dovrebbe essere omessa e fallirà i validatori JSON più rigidi). Ecco una rapida riscrittura a 58 byte che produce JSON valido (se più brutto per i lettori umani): $c||='{';s'"'\"'g;/=/&&say qq|$c"$`":"$'"|;$c=','}{say'}' mi aspetto che tu possa trovare qualcosa di un po 'più corto / più elegante.
trappola per topi

@mousetrapper Questo è un bel modo per evitare il BEGIN. OP consente esplicitamente le virgole finali però: "Le virgole finali sono consentite perché Minecraft le consente.". Sentiti libero di pubblicarlo come una nuova risposta, menzionando la differenza.
Sundar - Ripristina Monica il

Ah, sì, buon punto, ho perso quella frase nel post originale. L'assegnazione predefinita ha senso solo se stai cercando di variare il primo carattere, altrimenti il ​​tuo caso BEGINè ancora più breve nel caso in cui desideri semplicemente emettere "{". Mi piace la tua ENDtecnica evitante. Sapevo che -nponeva un ciclo efficace while(<>){} attorno al tuo codice; Non avevo idea di quanto fosse letterale.
trappola per topi

Sono stato anche piuttosto sorpreso, quando l'ho scoperto per la prima volta. È una di quelle funzionalità del Perl che si trova a cavallo tra uno strano hack e un modo geniale per eseguire TIMTOWDI. Ma me ne ero dimenticato, quindi il merito in questo caso va a Dennis nel thread dei consigli sul golf Perl 5 .
Sundar - Ripristina Monica il

2

Haskell , 75 71 byte

-4 byte grazie a Laikoni (usando la notazione sulla comprensione della lista)!

Funziona con più =su una riga:

f s='{':do{(a,_:b)<-span(/='=')<$>lines s;show a++':':show b++","}++"}"

Provalo online!

Spiegazione

Il termine span(/='=')<$>lines sdivide la stringa sul primo =, lasciandoci con ("<initial part>","=<remaining line>"). Fare una corrispondenza del modello (a,_:b)assicura che la linea non fosse vuota e allo stesso tempo rimuove il primo =.

Ora abbiamo solo bisogno di showentrambi ae b(racchiudendolo tra virgolette e citazioni in fuga), fare un po 'di formattazione ( :e ,personaggi) e, infine, racchiuderlo tra {}.


1
71 byte utilizzando do: provalo online!
Laikoni,

2

C (gcc) , 243 219 byte

Grazie a ceilingcat per il suggerimento.

Ho deciso di utilizzare una macchina a stati per gestire i tre casi (newline, chiave, valore) e si è rivelato abbastanza bene. Inoltre, ho avuto modo di ab utilizzare la caduta-through caratteristica switche l'operatore stringizing macro!

Sebbene la sfida non lo richiedesse, sono anche sfuggito al \personaggio secondo le specifiche JSON. Se quel carattere non sarà mai nell'input, allora &&c-92può essere rimosso per altri 5 byte.

#define p(s)printf(#s,c)
#define a(i)case i:
c,s;f(){for(p({);(c=getchar())>0;)switch(s){a(0)if(c<11)break;s++,p(\42);a(1)c==61?s++,p(":"):p(%c);break;a(2)c-34&&c-92?c==10?p(\42\54),s=0:p(%c):p(\\%c);}s-2||p(\42);p(});}

Provalo online!


Invio originale: 243 byte

L'invio originale ha mantenuto una spaziatura non necessaria come negli esempi JSON forniti.

#define p(s)printf(s,c)
#define a(i)case i:
c,s;f(){for(p("{\n");(c=getchar())>0;)switch(s){a(0)if(c<11)break;s++,p("  \"");a(1)c==61?s++,p("\": \""):p("%c");break;a(2)c-34&&c-39?c==10?p("\",\n"),s=0:p("%c"):p("\\%c");}s==2&&p("\"\n");p("}");}

Provalo online!


2

JavaScript, 66 63 62 byte

s=>JSON.stringify(o=/(.+)=(.+)/g,s.replace(o,(_,a,b)=>o[a]=b))

-3 byte grazie a @redundancy

-1 byte grazie a @ l4m2




@ l4m2 Oggetti RegExp con stringhe? Oggi ho imparato qualcosa di nuovo 🤯
darrylyeo,


1

Perl 6 , 48 byte

{to-json %(.lines.grep(?*)>>.split("=",2).flat)}

2 byte in meno se possiamo assumere esattamente 1 segno di uguale su una riga non vuota.

Provalo online!

Ungolfed:

{                   # An anonymous block, taking 1 string which ends in $_.
    to-json         # Convert a Perl 6 number, string, list or hash to JSON and return it.
    %(              # Force to hash (dictionary)
        .lines      # Break $_ (implicitly assumed) into a list of lines.
        .grep(?*)   # Pick only those that are True (non-empty).
        >>.         # For each element in the list, call the following method ... 
        split("=",2) # ... split the string at =, making at most 2 chunks.
        .flat       # That gives a list of 2-element lists. Flatten it.
    )               # List is converted into the hash like this: { first element => second element, third => fourth, ... }
}                   # Implicitly return

A proposito, la to-jsonroutine è deprecata, come ti dirà il compilatore, ma a chi importa.



1

Rubino, 59 + 5 = 64

Bisogni -rjson(+5)

->c{Hash[*c.split(?\n).map{|l|l.split ?=}.flatten].to_json}

Spiegazione:

->c{                                                      } # anonymous function with param c
    Hash[*                                       ]          # converts ["a", "b", "c", "d"] into {"a": "b", "c": "d"}
          c.split(?\n)                                      # splits c into lines
                      .map{|l|          }                   # map lines so each element represents
                              l.split ?=                    # an array of itself but split by =
                                         .flatten           # merges 2d array to 1d (also gets rid of empty elements for newlines
                                                  .to_json  # converts hash to json

1

JavaScript (ES6), 66 byte

s=>`{${s.replace(/"/g,'\\"').replace(/(.*)=(.*)/g,'"$1":"$2",')}}`

Suppone che ce ne sia solo uno =per riga

Test snippet

f=s=>`{${s.replace(/"/g,'\\"').replace(/(.*)=(.*)/g,'"$1":"$2",')}}`
<textarea id="i" onkeyup="o.innerText=f(i.value)"></textarea><pre id="o">


Dovrebbe essere 66 byte. \\ potrebbe essere stato analizzato come \ durante il conteggio della lunghezza.
ridondanza il

1
@redundancy Dovrei davvero smettere di usare "code".lengthnella console javascript per contare la lunghezza
Herman L

1

V , 30 byte

O{␛Í"/\\"
ggòeÉ"vyf=Plp$pa,òo}

Si aspetta un input alla volta. Lo snippet TIO esegue tutti i casi di test dati come un singolo input.

Sono nuovo delle mappature estese di V, quindi i suggerimenti sono sempre ben accetti!

Provalo online!

Spiegazione

O{␛                  # insert { on a new line above
   Í                 # global substitution across all lines
    "/\\"            #   " => \"
gg                   # go to first line
  ò                  # recursively...
   e                 #   forward to end of word; if at end of line, applies to next word below
    É"               #   prepend " to first non-whitespace char
      vy             #   copy current character (i.e. ")
        f=Plp        #   paste " before and after the next =
             $pa,    #   paste " at end of line and append ,
                 ò   # ...end
                  o} # insert } on a new line below

1

C (gcc) , 172 byte

#define p(s)printf(#s,c)
c,s;f(){for(p({);~(c=getchar());)s-2?c>10|s&&(s||(s+=p(\42)),c==61?s++,p(":"):p(%c)):c-34&&c-92?c==10?s=!p(\42\54):p(%c):p(\\%c);s-2||p(\42);p(});}

Provalo online!

Basato sull'implementazione di @ ErikF ma senza switch/case.

Versione leggermente non golfata

#define p(s)printf(#s,c)
c,s;
f(){
 for(p({);~(c=getchar());)
  s-2?
   c>10|s&&(
    s||
     (s+=p(\42)),
    c==61?
     s++,
     p(":")
    :
     p(%c)
   )
  :
   c-34&&c-92?
    c==10?
     s=!p(\42\54)
    :
     p(%c)
   :
    p(\\%c);
 s-2||p(\42);
 p(});
}

1

R, 118 byte

function(s){cat(paste("{",gsub("(.*)=(.*)","\"\\1\":\"\\2\",",gsub("\"","\\\\\"",gsub("\n{2,}","\n",s)),perl=T),"}"))}

Provalo online!


1

C (gcc) , 119 byte

#define p(s)printf(#s,c)
s;f(c){for(p({);~(c=getchar())|s;)c<11?s=s&&!p(",�"):c-61?s++||p(\42),p(\\u%04x):p(":");p(});}

Provalo online!


1

PHP, 87 byte

preg_match_all("/^(.*)=(.*)$/m",$argn,$m);echo json_encode(array_combine($m[1],$m[2]));

Esegui come pipe -nRo provalo online .

Inserisci \sprima $/mper le interruzioni di riga di Windows; \s*se le interruzioni di linea sono incerte.
Inserisci Udopo $/mse i valori contengono =.


1

Dardo , 142 114 108 byte

f(s)=>"""{${s.replaceAll('"','\\"').replaceAllMapped(RegExp(r'(.*)=(.*)'),(m)=>'"${m[1]}":"${m[2]}",')}}""";

Provalo online!

  • -28 byte eliminando la funzione json.encode e usando la normale creazione di stringhe
  • -6 byte rimuovendo la parola chiave "nuova" e alcuni spazi
  • 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.