Atualizador de arquivos de idiomas do Minecraft

11

Na versão 1.13, os arquivos de idioma do Minecraft passaram de um simples formato de chave = valor de várias linhas para JSON .

Desafio

Escreva um programa convertendo do formato original retornando uma string JSON. A entrada pode ser obtida usando qualquer método de entrada padrão, a saída deve ser json a partir de qualquer método de saída padrão

O formato original contém linhas com pares chave = valor, por exemplo

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

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

Deve ser convertido em um objeto JSON grande com chave = valor

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

Alguns detalhes

  • Qualquer JSON válido é permitido, desde que contenha apenas os pares chave / valor corretos. Vírgulas finais são permitidas porque o Minecraft permite.
  • As únicas coisas que devem ser evitadas são aspas. (Nenhuma linha nova, barras invertidas ou outras coisas que quebram json existiam no arquivo de idioma anterior à 1.13)
  • Linhas vazias devem ser ignoradas
  • As linhas contêm exatamente um é igual a

Casos de teste

Entrada:

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

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

Resultado:

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

Entrada:

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

Resultado:

{
  "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",
}

Entrada:

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

Resultado:

{
    "stat.mineBlock": "%1$s Mined",
    "stat.craftItem": "%1$s Crafted",
    "stat.useItem": "%1$s Used",
    "stat.breakItem": "%1$s Depleted"
}
pfg
fonte
1
Como se tile.dirt.nametorna "block.minecraft.dirt"?
Pavel
@Pavel uuh ... gritos. Corrigido isso. Isso não foi intencional
pfg 09/08/1918
5
É garantido que cada linha não vazia contenha exatamente 1 =?
User202729 9/08
@ user202729 yes
pfg
3
Eu gostaria de apostar que você realmente precisa de uma solução para esse problema e pretende usar uma para converter seus arquivos. :)
mbomb007

Respostas:

4

Python 3, 91 77 bytes

-14 bytes graças a OMᗺ

Eu pensei que a impressão de um dicionário Python seria próxima o JSON para torná-lo uma linguagem muito competitiva para esse desafio. No entanto, a representação em string dos dicionários python é diferente o suficiente do JSON, para que eu tenha melhor sorte usando a biblioteca JSON interna do python. Aposto que isso pode ser feito de forma mais sucinta em JavaScript.

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

Experimente Online!


Editar:

Bash + Sed, 68 63 bytes

Correção de bug graças ao OMᗺ e Night 2
-5 Bytes graças ao OMᗺ

Percebi que poderia ser mais eficiente em byte converter diretamente o texto em JSON sem agrupá-lo em um objeto, como foi minha abordagem para a solução python. Por byte, sed é a linguagem mais poderosa para substituição de regex que eu conheço.

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

Experimente Online!

Explicação

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
Zachary Cotton
fonte
8
Se você estiver respondendo em dois idiomas diferentes, sinta-se à vontade para postar isso como duas respostas separadas.
mbomb007
Para a festança resposta + sed, tente usar a -rbandeira de sed (+3 bytes) de modo que você não precisa para escapar à captura de grupos (-4 bytes) tio.run/##LYq7CgIxEEX7/...
user41805
4

Vim, 44 bytes

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

Explicação:

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

Ferrugem , 150 bytes

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

Experimente online!

É mais longo que Java?

Herman L
fonte
2

Retina 0.8.2 , 35 bytes

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

Experimente online! Seriam 34 bytes na Retina 1, como você pode usar em L$`.+vez de G`.e .+. Explicação:

"
\"

Fuja das aspas.

=
": "

Corrija o separador de chave / valor. (Se o valor puder conter a =, use 1`=a um custo de 2 bytes.)

G`.

Remova linhas vazias.

.+
    "$&",

Coloque cada linha entre aspas. (As aspas internas foram adicionadas anteriormente.)

^
{¶
$
¶}

Embrulhe toda a saída em {}s.

Neil
fonte
2

Casca , 22 bytes

A manipulação de cordas não é realmente a força de Husk, mas foi muito bem:

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

Experimente 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
ბიმო
fonte
Ironicamente, existe algo chamado "Husk" no Minecraft!
RedWolf Programas
2

Ruby , 56 bytes

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

+6 bytes para -rjsonsinalizador de intérprete.

Experimente online!

dkudriavtsev
fonte
1
@Piccolo você passou a bandeira -rjson?
Pfg
@pfg Uau, eu realmente deixei cair a bola naquele haha. Eu não só tinha esquecido de uso -rjson, mas também assumiu sem realmente verificar se o erro era a mesma que eu tinha começado mais cedo envolvendoto_h
Piccolo
2

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

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

Experimente online!


Versão de 58 bytes:

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

Experimente online!

sundar - Restabelecer Monica
fonte
Ambas as versões adicionam uma vírgula após cada par de chave: valor, que tecnicamente não é compatível com JSON (a vírgula final antes do fechamento }deve ser omitida e falhará na maioria dos validadores JSON estritos). Aqui está uma rápida reescrita de 58 bytes que produz JSON válido (embora mais feio para leitores humanos): $c||='{';s'"'\"'g;/=/&&say qq|$c"$`":"$'"|;$c=','}{say'}' Espero que você encontre algo um pouco mais curto / elegante.
Mousetrapper
@ mousetrapper Essa é uma boa maneira de evitar o BEGIN. O OP permite explicitamente vírgulas finais: "Vírgulas finais são permitidas porque o Minecraft permite.". Fique à vontade para postar isso como uma nova resposta, mencionando a diferença.
sundar - Restabelece Monica
Ah, sim, bom ponto, perdeu essa frase no post original. A atribuição padrão só faz sentido se você estiver tentando alterar o primeiro caractere; caso contrário, o seu BEGINainda será mais curto no caso em que você apenas deseja emitir o '{'. Eu gosto da sua ENDtécnica de evitar. Eu sabia que isso -ncolocava um loop efetivo while(<>){} em torno do seu código; Eu não tinha ideia do quão literal isso era.
Mousetrapper
Também fiquei bastante surpreso quando descobri isso. É um desses recursos do Perl que se estende pela linha entre um hack estranho e uma maneira brilhante de fazer o TIMTOWDI. Porém, eu tinha esquecido disso, então, neste caso, o crédito é dado a Dennis no tópico de dicas de golfe do Perl 5 .
sundar - Restabelece Monica 15/08/18
2

Haskell , 75 71 bytes

-4 bytes graças a Laikoni (usando notação do que compreensão da lista)!

Funciona com vários =em uma linha:

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

Experimente online!

Explicação

O termo span(/='=')<$>lines sdivide a corda no primeiro =, deixando-nos com ("<initial part>","=<remaining line>"). Fazer uma correspondência de padrões (a,_:b)garante que a linha não estivesse vazia e, ao mesmo tempo, remova a liderança =.

Agora só precisamos de showambos ae b(colocando-o entre aspas e citações escapando), fazer alguma formatação ( :e ,personagens) e, finalmente, coloque-o {}.

ბიმო
fonte
1
71 bytes usando do: Experimente online!
Laikoni 11/08/19
2

C (gcc) , 243 219 bytes

Agradecimentos a ceilingcat pela sugestão.

Decidi usar uma máquina de estado para lidar com os três casos (nova linha, chave, valor) e acabou bem. Além disso, eu tenho que ab usar a queda-through característica switchea macro operador stringizing!

Embora o desafio não o exigisse, também escapei do \personagem pela especificação JSON. Se esse caractere nunca estiver na entrada, &&c-92poderá ser removido por mais 5 bytes.

#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(});}

Experimente online!


Submissão original: 243 bytes

O envio original manteve espaçamento desnecessário, como nos exemplos JSON fornecidos.

#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("}");}

Experimente online!

ErikF
fonte
2

JavaScript, 66 63 62 bytes

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

-3 bytes graças a @redundancy

-1 byte graças a @ l4m2

darrylyeo
fonte
63 bytes no TIO
redundância
@ l4m2 Objetos RegExp com string? Aprendeu algo novo hoje 🤯
darrylyeo
1

Perl 6 , 48 bytes

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

2 bytes a menos se pudermos assumir exatamente 1 sinal de igual em uma linha não vazia.

Experimente 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 propósito, a to-jsonrotina está obsoleta, como o compilador dirá, mas quem se importa.

Ramillies
fonte
1

Ruby, 59 + 5 = 64

Necessidades -rjson(+5)

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

Explicação:

->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
Flautim
fonte
1

JavaScript (ES6), 66 bytes

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

Supõe que há apenas um = por linha

Snippet de teste

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

Herman L
fonte
Deve ter 66 bytes. \\ pode ter sido analisado como \ ao contar o comprimento.
redundância
1
@redundancy eu realmente deveria parar de usar "code".lengthno console javascript para contar o comprimento
Herman L
1

V , 30 bytes

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

Espera uma entrada de cada vez. O fragmento TIO executa todos os casos de teste fornecidos como uma única entrada.

Eu sou novo nos mapeamentos estendidos de V, portanto, as dicas são sempre bem-vindas!

Experimente online!

Explicação

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
redundância
fonte
1

C (gcc) , 172 bytes

#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(});}

Experimente online!

Baseado na implementação do @ ErikF, mas sem switch/case .

Versão ligeiramente não destruída

#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(});
}
teto
fonte
1

R, 118 bytes

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

Experimente online!

Chaos Manor
fonte
1

C (gcc) , 119 bytes

#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(});}

Experimente online!

l4m2
fonte
1

PHP, 87 bytes

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

Executar como tubo com -nRou experimente online .

Inserir \santes $/mpara quebras de linha do Windows; \s*se as quebras de linha são incertas.
Inserir Udepois $/mse os valores contiverem =.

Titus
fonte
1

Dardo , 142 114 108 bytes

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

Experimente online!

  • -28 bytes, livrando-se da função json.encode e usando a construção regular de cadeias
  • -6 bytes removendo a palavra-chave 'nova' e alguns espaços
  • Elcan
    fonte