Minecraft语言文件更新程序


11

在1.13版中,Minecraft语言文件从一种简单的多行key = value格式切换为JSON

挑战

编写一个从原始格式转换为返回JSON字符串的程序。可以使用任何标准输入方法进行输入,任何标准输出方法的输出必须为json

原始格式包含带有键=值对的行,例如

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

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

应该转换为key = value的一个大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的东西)
  • 空行应忽略
  • 行包含正好等于1的行

测试用例

输入:

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嗯...哎呀。固定的。那是无意的
pfg

5
是否保证每个非空行都精确地包含1 =
user202729

@ user202729是
pfg

3
我愿意打赌,您实际上需要针对此问题的解决方案,并打算使用一种解决方案来转换您的文件。:)
mbomb007

Answers:


4

Python 3,91 77字节

-14字节归功于OMᗺ

我认为Python字典的打印输出将足够接近JSON,从而使其成为应对这一挑战的极具竞争力的语言。但是,python词典的字符串表示形式与JSON足够不同,我使用python内置的JSON库更好。我敢打赌,这可以用JavaScript更加简洁地完成。

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

在线尝试!


编辑:

Bash + Sed,68 63字节

通过OMᗺ修复错误,通过OMᗺ修复Night 2
-5字节

我意识到,将文本直接转换为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 '18

对于bash + sed答案,请尝试使用-rsed标志(+3个字节),这样就无需转义捕获组(-4个字节)tio.run
##

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 }

3

,150字节

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

在线尝试!

它比Java长吗?


2

视网膜0.8.2,35字节

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

在线尝试!在Retina 1中将为34个字节,您可以L$`.+代替G`.和使用.+。说明:

"
\"

转义引号。

=
": "

修复键/值分隔符。(如果该值可能包含=,则使用1`=2个字节。)

G`.

删除空行。

.+
    "$&",

每行都用引号引起来。(内部引号已在前面添加。)

^
{¶
$
¶}

将整个输出包装为{}s。


2

外壳,22个字节

字符串操作并不是Husk真正的强项,但效果很好:

`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中有一种叫做“外壳”的东西!
Redwolf Programs '18年

2

Ruby,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.01058个 54字节

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

在线尝试!


58字节版本:

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

在线尝试!


这两个版本在每个key:value对之后都添加了一个逗号,这在技术上不符合JSON规范(结束时的最后一个逗号}应省略,并且将使大多数严格的JSON验证程序失败)。这是一个快速的58字节重写,它会产生有效的(对于人类读者而言较难看)JSON: $c||='{';s'"'\"'g;/=/&&say qq|$c"$`":"$'"|;$c=','}{say'}' 我希望您可以找到一些更短或更优雅的东西。
捕鼠器

@mousetrapper这是避免的好方法BEGIN。但是,OP明确允许尾随逗号:“允许尾随逗号,因为Minecraft允许它们。”。随意将其发布为新答案,并提及不同之处。
sundar-恢复莫妮卡

嗯,是的,很高兴,在原始帖子中错过了那句话。仅当您尝试更改第一个字符时,默认分配才有意义;否则BEGIN,在您只想发出'{'的情况下,您的名称会更短。我喜欢你的END避免技巧。我知道这在您的代码周围-n形成了 有效的 while(<>){}循环;我不知道那是多么的字面意思。
mousetrapper

当我第一次发现这一点时,我也感到非常惊讶。这是Perl的功能之一,跨越了怪异的hack和出色的TIMTOWDI方法之间的界线。但是我已经忘记了它,因此在这种情况下值得称赞的是Perl 5高尔夫球技巧中的丹尼斯。
sundar-恢复莫妮卡

2

Haskell75 71字节

感谢Laikoni -4个字节(使用对列表理解的do表示法)!

可以=在一行上使用多个:

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

在线尝试!

说明

这个词span(/='=')<$>lines s在第一个字符串上分割=,剩下我们一个("<initial part>","=<remaining line>")。进行模式匹配(a,_:b)可确保该行不为空,并同时删除前导=

现在,我们只需要show两个ab(引号和转义引号引起它),做一些格式(:,字符),最后附上它{}


1
71字节使用do在线尝试!
Laikoni '18

2

C(gcc)243219字节

多亏了ceilingcat的建议。

我决定使用状态机来处理这三种情况(换行符,键,值),结果非常好。另外,我得从头使用落空的功能switch和宏字符串化操作!

尽管挑战不是必需的,但我也按照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字符串化RegExp对象?今天学到了新东西new
darrylyeo '18


1

Perl 6,48个字节

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

如果我们可以假设非空行上的正好等于1,则少2个字节。

在线尝试!

取消高尔夫:

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

Ruby,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控制台中使用它来计算长度
Herman L

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

R,118字节

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

在线尝试!



1

PHP,87字节

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

与管道一起运行-nR在线尝试

Windows换行符\s之前插入$/m\s*如果不确定换行符。如果值包含,则
U后面插入。$/m=


1

142 114 108个字节

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

在线尝试!

  • -28字节,通过摆脱json.encode函数并使用常规字符串构建
  • 删除'new'关键字和几个空格可得到-6个字节
  • By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
    Licensed under cc by-sa 3.0 with attribution required.