Aktualizator plików językowych Minecraft

11

W 1.13 pliki językowe Minecraft zostały zmienione z prostego formatu wieloliniowego klucz = wartość na JSON .

Wyzwanie

Napisz program konwertujący z formatu oryginalnego zwracający ciąg JSON. Dane wejściowe można pobierać przy użyciu dowolnej standardowej metody wprowadzania, dane wyjściowe muszą być typu json z dowolnej standardowej metody wprowadzania

Oryginalny format zawiera na przykład wiersze z parami klucz = wartość

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

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

Należy przekonwertować na jeden duży obiekt JSON z kluczem = wartość

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

Trochę szczegółów

  • Dowolny prawidłowy JSON jest dozwolony, o ile zawiera tylko prawidłowe pary klucz / wartość. Końcowe przecinki są dozwolone, ponieważ pozwala na to Minecraft.
  • Jedynymi rzeczami, które należy uciec, są cytaty. (W wersji językowej wcześniejszej niż 1.13 nie było żadnych nowych linii, odwrotnych ukośników ani innych rzeczy przełamujących json)
  • Puste linie należy zignorować
  • Linie zawierają dokładnie jeden równy

Przypadki testowe

Wejście:

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

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

Wynik:

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

Wejście:

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

Wynik:

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

Wejście:

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

Wynik:

{
    "stat.mineBlock": "%1$s Mined",
    "stat.craftItem": "%1$s Crafted",
    "stat.useItem": "%1$s Used",
    "stat.breakItem": "%1$s Depleted"
}
pfg
źródło
1
Jak to tile.dirt.namesię stało "block.minecraft.dirt"?
Pavel
@Pavel uuh ... ups. Naprawiono to. To było niezamierzone
pfg
5
Czy gwarantuje się, że każda niepusta linia zawiera dokładnie 1 =?
user202729,
@ user202729 tak
PFG
3
Byłbym skłonny założyć się, że naprawdę potrzebujesz rozwiązania tego problemu i zamierzam użyć go do konwersji plików. :)
mbomb007,

Odpowiedzi:

4

Python 3, 91 77 bajtów

-14 Bajtów dzięki OMᗺ

Pomyślałem, że wydruk słownika Python byłby wystarczająco blisko JSON, aby uczynić go bardzo konkurencyjnym językiem dla tego wyzwania. Jednak reprezentacja łańcuchowa słowników Pythona jest na tyle różna od JSON, że lepiej mi było przy użyciu wbudowanej biblioteki JSON Pythona. Założę się, że można to zrobić bardziej zwięźle w JavaScript.

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

Wypróbuj online!


Edytować:

Bash + Sed, 68 63 bajtów

Naprawiono błędy dzięki OMᗺ i Night 2
-5 Bytes dzięki OMᗺ

Uświadomiłem sobie, że bardziej efektywna bajtowo może być bezpośrednia konwersja tekstu do JSON bez wiązania go w obiekt, podobnie jak moje podejście do rozwiązania python. Sedno jest najsilniejszym językiem do zastępowania wyrażeń regularnych, jaki znam.

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

Wypróbuj online!

Wyjaśnienie

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
źródło
8
Jeśli odpowiadasz w dwóch różnych językach, możesz zamieścić to jako dwie osobne odpowiedzi.
mbomb007,
W przypadku odpowiedzi bash + sed spróbuj użyć -rflagi dla sed (+3 bajty), aby nie trzeba było uciekać przed grupami przechwytywania (-4 bajty) tio.run/##LYq7CgIxEEX7/…
user41805
4

Vim, 44 bajty

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

Wyjaśnienie:

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

Rdza , 150 bajtów

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

Wypróbuj online!

Czy jest dłuższy niż Java?

Herman L.
źródło
2

Retina 0.8.2 , 35 bajtów

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

Wypróbuj online! W Retinie 1 byłoby 34 bajtów, których można użyć L$`.+zamiast G`.i .+. Wyjaśnienie:

"
\"

Unikaj cytatów.

=
": "

Napraw separator klucz / wartość. (Jeśli wartość może zawierać a =, użyj 1`=kosztu 2 bajtów.)

G`.

Usuń puste linie.

.+
    "$&",

Zawiń każdą linię w cudzysłów. (Wewnętrzne cytaty zostały dodane wcześniej).

^
{¶
$
¶}

Zawiń całe wyjście w {}s.

Neil
źródło
2

Łuska , 22 bajty

Manipulowanie strunami nie jest tak naprawdę siłą Husky, ale całkiem nieźle:

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

Wypróbuj 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
ბიმო
źródło
Jak na ironię, w Minecraft jest coś o nazwie „Łuska”!
Programy Redwolf,
2

Rubinowy , 56 bajtów

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

+6 bajtów dla -rjsonflagi interpretera.

Wypróbuj online!

dkudriavtsev
źródło
1
@Piccolo zdałeś flagę -rjson?
pfg,
@pfg Wow, naprawdę upuściłem piłkę na to haha. Nie tylko zapomniałem użyć -rjson, ale również założyłem, że nie sprawdziłem, czy błąd był taki sam, jak wcześniej, z udziałemto_h
Piccolo,
2

Perl 5 -nl -M5.010 , 58 54 bajtów

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

Wypróbuj online!


Wersja 58-bajtowa:

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

Wypróbuj online!

sundar - Przywróć Monikę
źródło
Obie wersje dodają przecinek po każdej parze klucz: wartość, która technicznie nie jest zgodna z JSON (ostatni przecinek przed zamknięciem }powinien zostać pominięty i zawiedzie najbardziej rygorystyczne walidatory JSON). Oto szybkie, 58-bajtowe przepisywanie, które daje poprawne (jeśli brzydsze dla ludzkich czytelników) JSON: $c||='{';s'"'\"'g;/=/&&say qq|$c"$`":"$'"|;$c=','}{say'}' Oczekuję, że znajdziesz coś nieco krótszego / bardziej eleganckiego.
mousetrapper
@mousetrapper To dobry sposób na uniknięcie BEGIN. OP wyraźnie dopuszcza przecinki końcowe: „Przecinki końcowe są dozwolone, ponieważ pozwala na to Minecraft.”. Opublikuj to jako nową odpowiedź, podając różnicę.
Sundar - Przywróć Monikę
Ach, tak, dobra uwaga, przeoczyłem to zdanie w oryginalnym poście. Domyślne przypisanie ma sens tylko wtedy, gdy próbujesz zmienić pierwszą postać, w przeciwnym razie BEGINnadal będziesz krótszy w przypadku, gdy chcesz po prostu emitować „{”. Lubię twoją ENDtechnikę unikania. Wiedziałem, że -numieszcza skuteczną while(<>){} pętlę wokół twojego kodu; Nie miałem pojęcia, jak to było dosłowne.
mousetrapper
Byłem też dość zaskoczony, kiedy to odkryłem. Jest to jedna z tych funkcji Perla, która łączy granicę między dziwnym włamaniem a świetnym sposobem na zrobienie TIMTOWDI. Jednak zapomniałem o tym, więc to zasługa Dennisa w temacie Perl 5 wskazówek golfowych .
Sundar - Przywróć Monikę
2

Haskell , 75 71 bajtów

-4 bajty dzięki Laikoni (używając notacji zamiast listowej interpretacji )!

Działa z wieloma =w jednej linii:

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

Wypróbuj online!

Wyjaśnienie

Termin span(/='=')<$>lines sdzieli ciąg na pierwszy =, pozostawiając nam ("<initial part>","=<remaining line>"). Wykonanie dopasowania wzorca (a,_:b)zapewnia, że ​​linia nie była pusta, a jednocześnie usuwa wiodące =.

Teraz musimy tylko showjedno ai drugie b(umieszczając je w cudzysłowach :i ,znaki ucieczkowe), dokonujemy formatowania ( i znaków) i na końcu je zamykamy {}.

ბიმო
źródło
1
71 bajtów przy użyciu do: Wypróbuj online!
Laikoni,
2

C (gcc) , 243 219 bajtów

Dzięki pułapkowi cat za sugestię.

Zdecydowałem się użyć maszyny stanów do obsługi trzech przypadków (nowa linia, klucz, wartość) i okazało się, że całkiem nieźle. Ponadto, mam do ab użyć Fall-poprzez cechy switchi makro operatora stringizing!

Chociaż wyzwanie nie wymagało tego, uciekłem również \postaci zgodnie ze specyfikacją JSON. Jeśli ten znak nigdy nie będzie na wejściu, &&c-92można go usunąć na 5 kolejnych bajtów.

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

Wypróbuj online!


Oryginalne przesłanie: 243 bajty

Oryginalne zgłoszenie zachowało niepotrzebne odstępy, jak w dostarczonych przykładach JSON.

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

Wypróbuj online!

ErikF
źródło
2

JavaScript, 66 63 62 bajty

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

-3 bajty dzięki @redundancy

-1 bajt dzięki @ l4m2

darrylyeo
źródło
63 bajty na TIO
redundancja
@ l4m2 Strunowe obiekty RegExp? Nauczyłem się dziś czegoś nowego dar
darrylyeo
1

Perl 6 , 48 bajtów

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

2 bajty mniej, jeśli możemy założyć dokładnie 1 znak równości w niepustej linii.

Wypróbuj online!

Nie golfowany:

{                   # 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

Nawiasem mówiąc, to-jsonprocedura jest przestarzała, jak powie kompilator, ale kogo to obchodzi.

Ramillies
źródło
1

Rubin, 59 + 5 = 64

Potrzebuje -rjson(+5)

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

Wyjaśnienie:

->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
Pikolo
źródło
1

JavaScript (ES6), 66 bajtów

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

Zakłada się, że jest tylko jeden =wiersz

Testowanie fragmentu kodu

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

Herman L.
źródło
Powinien mieć 66 bajtów. \\ mógł zostać przeanalizowany jako \ podczas liczenia długości.
redundancja,
1
@ redundancy Naprawdę powinienem przestać używać "code".lengthw konsoli javascript, aby policzyć długość
Herman L
1

V , 30 bajtów

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

Oczekuje jednego wejścia na raz. Fragment kodu TIO uruchamia wszystkie podane przypadki testowe jako jedno wejście.

Jestem nowy w rozszerzonych mapowaniach V, więc wskazówki są zawsze mile widziane!

Wypróbuj online!

Wyjaśnienie

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
nadmiar
źródło
1

C (gcc) , 172 bajty

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

Wypróbuj online!

Na podstawie implementacji @ ErikF, ale bez switch/case.

Wersja lekko nie golfowa

#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(});
}
sufitowy
źródło
1

R, 118 bajtów

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

Wypróbuj online!

Dwór Chaosu
źródło
1

C (gcc) , 119 bajtów

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

Wypróbuj online!

l4m2
źródło
1

PHP, 87 bajtów

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

Uruchom jako potok z -nRlub spróbuj online .

Wstaw \sprzed $/mpodziały wiersza systemu Windows; \s*jeśli łamanie linii jest niepewne.
Wstaw Upo, $/mjeśli wartości zawierają =.

Tytus
źródło
1

Dart , 142 114 108 bajtów

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

Wypróbuj online!

  • -28 bajtów poprzez pozbycie się funkcji json.encode i użycie regularnego budowania łańcucha
  • -6 bajtów poprzez usunięcie słowa kluczowego „new” i kilku spacji
  • Elcan
    źródło