Обновление языковых файлов Minecraft


11

В 1.13 языковые файлы Minecraft были переведены из простого многострочного формата ключ = значение в JSON .

Вызов

Напишите программу, конвертирующую из исходного формата, возвращающую строку JSON. Ввод может быть выполнен с использованием любого стандартного метода ввода, вывод должен быть json из любого стандартного метода вывода

Исходный формат содержит строки с парами ключ = значение, например

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

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

Должен быть преобразован в один большой объект JSON с ключом = значением

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

Некоторые детали

  • Разрешен любой допустимый JSON, если он содержит только правильные пары ключ / значение. Конечные запятые разрешены, потому что Minecraft позволяет им.
  • Единственное, что нужно избежать, это кавычки. (До версии 1.13 в языковом файле не было ни новой строки, ни обратной косой черты, ни других вещей, разрушающих json)
  • Пустые строки следует игнорировать
  • Строки содержат ровно одно равное

Тестовые случаи

Входные данные:

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

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

Выход:

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

Входные данные:

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

Выход:

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

Входные данные:

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

Выход:

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

1
Как tile.dirt.nameстать "block.minecraft.dirt"?
Павел

@Pavel uuh ... упс. Исправлено Это был непреднамеренный
PFG

5
Гарантируется ли, что каждая непустая строка содержит ровно 1 =?
user202729

@ user202729 да
pfg

3
Я был бы готов поспорить, что вам действительно нужно решение этой проблемы, и мы собираемся использовать его для конвертации ваших файлов. :)
mbomb007

Ответы:


4

Python 3, 91 77 байт

-14 байт благодаря OMᗺ

Я думал, что распечатка словаря Python будет достаточно близка к JSON, чтобы сделать его очень конкурентоспособным языком для этой задачи. Однако строковое представление словарей Python достаточно отличается от JSON, так что мне повезло больше, если использовать встроенную библиотеку JSON Python. Держу пари, что это можно сделать более кратко в JavaScript.

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

Попробуйте онлайн!


Редактировать:

Баш + Сед, 68 63 байта

Исправление ошибки благодаря OMᗺ и Night 2
-5 байт благодаря OMᗺ

Я понял, что может быть более эффективно использовать байты для непосредственного преобразования текста в JSON без объединения его в объект, как это было в моем подходе к решению на python. По сути, sed - это самый мощный язык для замены регулярных выражений, который я знаю.

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

Попробуйте онлайн!

объяснение

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
Если вы отвечаете на двух разных языках, не стесняйтесь опубликовать это как два отдельных ответа.
mbomb007

Для ответа bash + sed попробуйте использовать -rфлаг для sed (+3 байта), чтобы вам не нужно было избегать групп захвата (-4 байта) tio.run/##LYq7CgIxEEX7/…
user41805

4

Vim, 44 байта

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

Объяснение:

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


2

Сетчатка 0.8.2 , 35 байт

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

Попробуйте онлайн! Было бы 34 байта в Retina 1, как вы можете использовать L$`.+вместо G`.и .+. Объяснение:

"
\"

Избежать кавычек.

=
": "

Исправьте разделитель ключ / значение. (Если значение может содержать a =, используйте 1`=по стоимости 2 байта.)

G`.

Удалить пустые строки.

.+
    "$&",

Оберните каждую строку в кавычки. (Внутренние цитаты были добавлены ранее.)

^
{¶
$
¶}

Оберните весь вывод в {}с.


2

Шелуха , 22 байта

Манипулирование строками на самом деле не является сильной стороной Хаска, но оно довольно хорошо:

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

Попробуйте онлайн!

                      ¶  -- 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

По иронии судьбы, в Minecraft есть нечто, называемое «шелуха»!
Программы

2

Рубин , 56 байт

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

+6 байт для -rjsonфлага интерпретатора.

Попробуйте онлайн!


1
@Piccolo ты пропустил флаг -rjson?
pfg

@pfg Ух ты, я действительно бросил мяч на этом хаха. Я не только забыл использовать -rjson, но и предположил, фактически не проверяя, была ли ошибка той же самой, которую я получил раньше, с участиемto_h
Piccolo

2

Perl 5 -nl -M5.010 , 58 54 байта

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

Попробуйте онлайн!


58-байтовая версия:

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

Попробуйте онлайн!


Обе версии добавляют запятую после каждой пары ключ: значение, которая технически несовместима с JSON (последняя запятая перед закрытием }должна быть опущена, и в ней не пройдут самые строгие валидаторы JSON). Вот быстрое 58-байтовое переписывание, которое дает действительный (хотя и уродливее для читателей) JSON: $c||='{';s'"'\"'g;/=/&&say qq|$c"$`":"$'"|;$c=','}{say'}' Я ожидаю, что вы можете найти что-то более короткое / более элегантное.
мышеловка

@mousetrapper Это хороший способ избежать BEGIN. OP явно разрешает конечные запятые, хотя: «Конечные запятые разрешены, потому что Minecraft позволяет им». Не стесняйтесь размещать это как новый ответ, упоминая разницу.
sundar - Восстановить Монику

Ах, да, хорошая мысль, пропустил это предложение в оригинальном посте. Задание по умолчанию имеет смысл только в том случае, если вы пытаетесь изменить первый символ, в противном случае ваше значение BEGINбудет еще короче в случае, когда вы просто хотите испустить '{'. Мне нравится ваша ENDтехника избегания. Я знал, что -nэто делает эффективный while(<>){} цикл вокруг вашего кода; Я понятия не имел, насколько буквальным это было.
мышеловка

Я тоже был очень удивлен, когда впервые узнал об этом. Это одна из тех возможностей Perl, которая пересекает грань между странным взломом и блестящим способом создания TIMTOWDI. Я забыл об этом, хотя, так что заслуга в этом в этом случае принадлежит Деннису в ветке Perl 5 .
sundar - Восстановить Монику

2

Haskell , 75 71 байт

-4 байта благодаря Лайкони (используя do-нотацию над списком-пониманием)!

Работает с несколькими =на одной строке:

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

Попробуйте онлайн!

объяснение

Термин span(/='=')<$>lines sразбивает строку на первый =, оставляя нас с ("<initial part>","=<remaining line>"). Выполнение сопоставления с шаблоном (a,_:b)гарантирует, что строка не будет пустой, и в то же время удаляет начальную строку =.

Теперь нам нужно только showоба aи b(заключить его в кавычки и экранировать кавычки), выполнить некоторое форматирование ( :и ,символы) и, наконец, заключить его в {}.



2

C (gcc) , 243 219 байт

Благодарю потолочный кот за предложение.

Я решил использовать конечный автомат для обработки трех случаев (новая строка, ключ, значение), и это оказалось довольно хорошо. Кроме того , я должен абам использовать завал через особенность switchи макро - оператор stringizing!

Хотя вызов не требовал этого, я также избежал \персонажа согласно спецификации JSON. Если этот символ никогда не будет на входе, то &&c-92можно удалить еще 5 байтов.

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

Попробуйте онлайн!


Исходное представление: 243 байта

Исходное представление оставляло ненужный интервал, как в предоставленных примерах 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("}");}

Попробуйте онлайн!


2

JavaScript, 66 63 62 байта

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

-3 байта благодаря @redundancy

-1 байт благодаря @ l4m2




@ l4m2 Stringified RegExp объекты? Узнал что-то новое сегодня 🤯
darrylyeo


1

Perl 6 , 48 байт

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

На 2 байта меньше, если мы можем принять ровно 1 знак равенства на непустой строке.

Попробуйте онлайн!

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

Кстати, to-jsonрутина устарела, как вам скажет компилятор, но кого это волнует.



1

Рубин, 59 + 5 = 64

Необходимо -rjson(+5)

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

Объяснение:

->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 байт

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

Предполагается, что есть только один = на линию

Тестовый фрагмент

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


Должно быть 66 байтов. \\ мог быть проанализирован как \ при подсчете длины.
резервирование

1
@redundancy Я действительно должен прекратить использовать "code".lengthв консоли javascript для подсчета длины
Герман Л

1

V , 30 байтов

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

Ожидается один вход за раз. Фрагмент TIO запускает все заданные тестовые случаи как один вход.

Я новичок в расширенном отображении V, поэтому советы всегда приветствуются!

Попробуйте онлайн!

объяснение

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 байта

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

Попробуйте онлайн!

На основе реализации @ ErikF, но без switch/case.

Слегка негольфированная версия

#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

PHP, 87 байт

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

Запустите как трубу с -nRили попробуйте онлайн .

Вставить \sперед $/mWindows для разрывов строк; \s*если разрывы строк не определены.
Вставьте Uпосле, $/mесли значения содержат =.


1

Дротик , 142 114 108 байт

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

Попробуйте онлайн!

  • -28 байт, избавившись от функции json.encode и используя обычное построение строк
  • -6 байт, удалив ключевое слово 'new' и несколько пробелов
  • Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
    Licensed under cc by-sa 3.0 with attribution required.