解密神经性青蛙


28

解密神经性青蛙

既然Puzzling.SE终于破解了我的两栖类密码,让我们编写一个程序或函数对其解密吧!

(如果您想在迷惑之前先看一下它,请立即单击上面的链接。)


密码如何工作

神经症蛙ö ught向rel 一个 X在中号 UD浴场(“神经质青蛙”的简称),每一个字母被加密为一个或两个词:

  • 非斜体字的长度表示字母。
    • neurotic => 8个字母=> H
    • frogs => 5个字母=> E
    • perpendicular => 13个字母= M
  • 包含斜体的单词会修改以下单词,如果斜体单词的长度为奇数,则增加10;如果斜体单词的长度为偶数,则增加20。任何或所有单词都可以斜体显示。斜体字总是跟着非斜体字。
    • *o*ught to =>奇数,2 => 12 => L
    • lo*u*nging calms =>偶数= 5 => 25 => Y

每个明文单词对应一个密文句子,每个明文句子对应一个密文段落。

输入格式

您的程序或功能应以“神经青蛙”的形式输入消息,格式为Markdown。输入将仅包含可打印的ASCII和换行符。

  • 单词是与正则表达式匹配的字符行[A-Za-z0-9']
    • 数字和字母均计入一个单词的长度。QB64代表D
    • 注意:撇号不会计入单词的长度。Isn't代表D,不是E
  • 斜体字母包裹在一个星号(*letters*)中。
    • 一个或多个连续字母可以斜体显示,直到整个单词(masseus*es**all*);单词中的多个非连续字母也可以用斜体(g*e*n*e*rates)表示。
    • 斜体字不包含多个单词,不包含标点符号,也不包含撇号。
    • 未配对的星号和多个相邻的星号将永远不会发生。
  • 标点是以下任意字符:.,?!:;-()"
    • 句子中的单词由一个或多个标点符号和/或单个空格分隔。例如:*all* welcomedtoad*s*, newtsEver*y*one--frogscap... blissthey're (I
    • 句子以一个或多个标点符号结尾,并以双倍空格隔开: Th*e* Montgomery A*m*phibian Salon! Come luxuriate today!
    • 段落由单个换行符分隔。(段落的最后一句在末尾仍具有一个或多个标点符号。)

其他字符将不会出现在输入中,并且不需要进行处理。

您的代码可能会自行决定期望输入中包含一个尾随换行符。

输出格式

解密输入的结果将是一个或多个句子。明文字母可以是大写和小写的任意组合。句子中的单词必须用单个空格分隔。句子必须以句号(.)并用单个空格分隔。您可以在最后一句之后输出尾随空格。您的输出全部在一行上,但是您可以输出尾随的换行符。

杂项详细信息

您的代码可以使用任何标准输入和输出方法。它必须以多行字符串而不是列表或其他数据结构的形式接收输入,并且必须输出字符串。

以字节为单位的最短代码胜出!

测试用例

-->
Neurotic Frogs *O*ught To Rel*a*x In *M*ud Baths!
<--
HELLO.

-->
Business standards all*o*w only *adult* amphibians.
<--
HINT.

-->
Rejoice, *a*ll frogs an*d* toads also!  Montgomery Sal*o*n opens up!  Ha*pp*y throng fill*s* street ecstatically!
<--
GOOD JOB PPL.

-->
I like 3.1415926535897.
IM*O*, it's a *b*la*st*, yeah!
<--
ADAM. MAN.

-->
*I*, happily, *th*anks 2 u *e*ditin*g* specific wor*ding*--clarifying a *bit*--betterment :D!
<--
QUARTATA.

-->
Perpendicular l*ou*nging calms.  *A* frog, a m*u*d cap... bliss!  Wallowing g*e*n*e*rates happiness.  Amphibian sp*a* isn't expensive--seventy d*o*llars--cheap!  That'*s* not *a* large e*x*pens*e* from an*y* discerning fr*o*g's money, unlik*e* Super 8.
Ever*y*one--frogs, toad*s*, newts, *a*nd salamanders!  G*e*t a wonderful shiat*s*u, or recei*v*e an other kind.  Masseus*es* are her*e* today!  Invite a fianc*e*e, supervisor, roommate, niece: *all* welcomed!
Y*o*u simply ne*v*er believed these p*o*ssibilitie*s*; they're (I *swear*) absolute truth!  Th*e* Montgomery A*m*phibian Salon!  Come luxuriate today!
<--
MY NAME IS INIGO MONTOYA. YOU KILLED MY FATHER. PREPARE TO DIE.

4
+1 for the princess bride input. Oh, and for your skill, that too.
Magic Octopus Urn

Is a word containing italics guaranteed to be followed by one not containing italics?
R. Kap

@R.Kap Correct. I've edited the question to clarify that.
DLosc

Answers:


5

Perl, 72 bytes

#!perl -n
$x=/\*/?2-y/'//c%2:!print/ /?$':chr$x.0+y/'//c+64for/[\w*']+|  /g,' . '

Counting the shebang as one, input is taken from stdin.

Sample Usage

$ more in.dat
Neurotic Frogs *O*ught To Rel*a*x In *M*ud Baths!
Perpendicular l*ou*nging calms.  *A* frog, a m*u*d cap... bliss!  Wallowing g*e*n*e*rates happiness.  Amphibian sp*a* isn't expensive--seventy d*o*llars--cheap!  That'*s* not *a* large e*x*pens*e* from an*y* discerning fr*o*g's money, unlik*e* Super 8.
Ever*y*one--frogs, toad*s*, newts, *a*nd salamanders!  G*e*t a wonderful shiat*s*u, or recei*v*e an other kind.  Masseus*es* are her*e* today!  Invite a fianc*e*e, supervisor, roommate, niece: *all* welcomed!
Y*o*u simply ne*v*er believed these p*o*ssibilitie*s*; they're (I *swear*) absolute truth!  Th*e* Montgomery A*m*phibian Salon!  Come luxuriate today!

$ perl neurotic-frogs.pl < in.dat
HELLO. MY NAME IS INIGO MONTOYA. YOU KILLED MY FATHER. PREPARE TO DIE.

1
I'm awarding the bounty to this answer, since it's the shortest one at the end of the bounty period besides my own (indeed, the only one that came anywhere close).
DLosc

4

JavaScript (ES6), 172 169 157 150 bytes

Saved 10 bytes thanks to @Neil

x=>x.match(/[\w'*]+|\s+/g).map(y=>y[0]==" "?y[1]:y==`
`?". ":/\*/.test(y,l+=y.match(/\w/g).length)?(l=l%2*10+19,""):l.toString(36,l=9),l=9).join``+"."

Can probably be further improved. Outputs in all lowercase.


Save 2 bytes by moving the i=0 into the toString.
Neil

Out of interest, I had a go at fixing those bugs and came up with this: x=>x.replace(/([\w*']+)[^\w\n*' ]* ?( ?)/g,(_,y,z)=>/\*/.test(y,l=y.replace(/'/g ,"").length)?(i=l%2||2,""):l+i*10+9).toString(36,i=0)+z,i=0).replace(/\n|$/g,". ")
Neil

Seems to work in it's current form.
primo

@Neil Thanks. That saves 12 bytes, but it doesn't work on the last test case. Fixing that adds 9 for a net shortening of 3 bytes.
ETHproductions

@Neil Getting rid of .replace and just using .match saved another 12 bytes.
ETHproductions

3

Python 2, 238 221 218 214 207 205 bytes

from re import*
def f(x):
 d='';m=0
 for w in split(r"[^\w\d*'~\n]+",sub('  ','~',x))[:-1]:l=len(sub("[*'~\n]",'',w));q='*'in w;d+='. '[w[0]>'}':]*(w[0]in'~\n')+chr(64+l+m)[q:];m=(2-l%2)*10*q
 print d+'.'

Uses lots of regex to do the processing. We transform the double-space into ~ and use that to process it. ~ and \n are handled specially.

The biggest character gain comes from the preprocessing of the input in the for line; this can definitely be golfed further.

Ideone it! (all test cases)

Saved 7 bytes thanks to DLosc!


3

Pip, 65 64 bytes

The score is 62 bytes of code + 2 for the -rs flags.

Flg{O{{(zy*t+#a-1)X!Y'*Na&2-#a%2}MJa@`[\w*]+`}MlRM''^sX2O". "}

Try it online!

Explanation

The -r flag reads all lines of stdin and stores a list of them in g. The -s flag sets the output format of lists to space-separated.

The easiest way to read this code is from the outside in:

Flg{...}                   For each line l in g, do:

O{...}MlRM''^sX2O". "      Translate a paragraph into a sentence of plaintext:
       lRM''               Remove apostrophe characters
            ^sX2           Split on "  " into sentences
 {...}M                    Map the below function to each sentence
O                          Output the result list, space-separated, without newline
                O". "      Output that string, without newline

{...}MJa@`[\w*]+`          Translate a sentence into a word of plaintext:
       a@`[\w*]+`          Find all matches of regex (runs of alphanumeric and *)
{...}MJ                    Map the below function to each word and join into string

(zy*t+#a-1)X!Y'*Na&2-#a%2  Translate a word into a letter of plaintext:
      #a-1                 Length of word minus 1
  y*t+                     Add 10 or 20 if y is set (see below)
(z        )                Use that number to index into lowercase alphabet
              '*Na&        Count * characters in word, logical AND with...
                   2-#a%2  2 if word is even length, 1 if odd
             Y             Yank that value into y, to modify the following word
           X!              String multiply the character by not(y)
                           If y is truthy, the word had italics, and we get ""
                           If y is falsy, the word had no italics, and we get a letter

Seems unbeatable.
primo

1

Python 2.7, 390 342 341 339 335 bytes:

from re import*
def F(i):
 W=X="";S,s=split,sub;D='[^\w\s*]';Q=lambda c,t:len(s(D,X,c.group()).split()[t])
 for m in S('\W\n',s(D+"*\w*\*\w+\*.*?(?=\s) \w+",lambda v:"a"*([20,10][Q(v,0)%2]+Q(v,1)),s("'",X,s("--"," ",i)))):
  for g in S('\W  ',m):
   for q in S('\W',g):
    W+=chr(64+len(q))
   W+=" "
  W=W[:-1]+". "
 print s("@",X,W)

Takes input in the format:

F('''Multi or Single-lined String''')

Can be golfed down a lot more, which I will do whenever I get the chance.

Repl.it with All Test Cases!

Explanation:

Uses the immense power of Python's regular expression built-ins to decipher the input. This is the fundamental process the function goes through for each input:

  1. Firstly, all -- are replaced with a single space, and every apostrophe is removed. Then, all words containing italicized components and the word proceeding it are both matched in one string and replaced with 10 + len(second word) number of consecutive as if the length of the first word is odd, and 20 + len(second word) consecutive as otherwise. This makes use of the following regular expression:

    [^\w\s*]*\w*\*\w+\*.*?(?=\s) \w+

    For example, if we have the sentence Perpendicular l*ou*nging calms., l*ou*nging calms will be replaced with aaaaaaaaaaaaaaaaaaaaaaaaa, or 25 as, since l*ou*nging has an even number of characters and calms has 5. 20+5=25.

  2. Now, the newly modified input is split at each punctuation mark followed by a newline (\n) to get the paragraphs, then each paragraph is split at each punctuation followed by 2 spaces to get the sentences, and finally, each sentence is split into words along any punctuation including a space. Then, for each word (including the runs of consecutive as), we add on to a string W the letter corresponding to the unicode code point 64 (the unicode code point of the character before A, which is @) plus len(word). We then add a single space to W once all the words of a sentence have been exhausted, and when all the sentences in a paragraph are exhausted, we add a . followed by a single space.

  3. Finally, after the entire input has been gone through, W is output to stdout as the deciphered message.


Minor nitpick: spec says output sentences are separated by single space, not double (this change also saves a byte). Initial golfing suggestion: since you're importing everything from re, use sub instead of str.replace. More general golfing suggestion: it's probably more efficient to treat everything that's not a word or * as punctuation. Saves on big huge character classes.
DLosc

@DLosc Oh, my bad. I thought the spec was to separate sentences in the output by 2 spaces. I'll fix that. Also, thanks for the golfing suggestions! I'll see what I can do with those.
R. Kap

1

PHP, 196 Bytes

<?preg_match_all("#[\w*']+|  |$#m",$_GET[s],$m);foreach($m[0]as$s){if(!$s||$s=="  ")echo!$s?". ":" ";else{$l=$p+64+strlen(str_replace("'","",$s));if(!$p=strstr($s,"*")?20-$l%2*10:0)echo chr($l);}}

If I could assume that there is only one Apostrophe in the middle of a word 194 Bytes

<?preg_match_all("#[\w*]+(<?=')[\w*]+|[\w*]+|  |$#m",$_GET[s],$m);foreach($m[0]as$s){if(!$s||$s=="  ")echo!$s?". ":" ";else{$l=$p+64+strlen($s);if(!$p=strstr($s,"*")?20-$l%2*10:0)echo chr($l);}}

@DLosc It was urlencoded %0A as a function rawurlencode("\n"). I prefer in this case a form with a textarea for the input and so my html site makes it automatically to encode the string
Jörg Hülsermann

@DLosc I suspect that error_reporting in the php.ini is on. try 'error_reporting(0);' after the <?. One error belongs to $_GET[s] it works but correct is $_GET["s"] and it's better to declareand initialize the variable $p=0; before the loop. Now my question at you is: Can I ssume that in one Word is only one Apostrophe in the middle of the Word?
Jörg Hülsermann

@DLosc for multiple Apostrophes I must use my first answer. The second - 2 Bytes works only with one Apostroph in the middle if the word.
Jörg Hülsermann

I figured out what my problem was--my server doesn't have short opening tags enabled. Changing to <?php worked.
DLosc

@Dlosc I have never use <? in reality. I use the short tag only in my post here. Now I know that it can resut in a blank page.
Jörg Hülsermann

1

PHP, 231 226 228 bytes

for a start

<?preg_match_all("#([\w\*']+)([^\w\*']*)#",$argv[1],$m,2);foreach($m as list(,$a,$b)){$e=strlen(strtr($a,["'"=>""]))+$d;if(!$d=strstr($a,'*')?$e%2*10:0)echo chr($e+64),strpos(".$b","
")?". ":(strpos(".$b","  ")?" ":"");}echo".";

Save to file, rund php <scriptpath> <text>. Escape newlines in the text to make it work in shell.


1
Can you give some instructions on running this? It looks like it reads input from $argv[1], but I don't know how that approach will work when input contains newlines. I tried "Neurotic Frogs *O*ught To Re*a*x In *M*ud Baths!" as a command-line argument and got IFHCHCFF. for output (as well as an Undefined variable: d warning).
DLosc

@DLosc: That notice (not a warning) should not be there with default settings. The easiest way is to prepend <?, save it to a file and call that with php <filename> <string>. I may have to add 2 to the byte count.
Titus

@Titus If you begin with <?, you can also end with ?>., for a net gain for 1. FWIW, I get IFHCMFF. for the first test case (using PHP 5.5.21 64-bit, VC14). Using $argn with -F may also be an option.
primo

What I mean is, I don't see how php <filename> <string> is possible when <string> can contain newlines.
DLosc

@DLosc: fixed the bug. For the newlines: escape them.
Titus
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.