记住23940的助记符


19

系统主要记忆用于转换数字成单词,这样他们可以更容易地存储设备。

它基于单词的语音发音方式,但是为了使问题简单易懂,我们只关心单词的拼写方式。这意味着会有一些不正确的转换,但是没关系。

使用简化的主系统将数字转换成单词:

  • 0s或替换每个z。(有些可能是s,有些可能是z。下同。)
  • 1td或替换它们th
  • 替换每个2n
  • 替换每个3m
  • 替换每个4r
  • 替换每个5l
  • 6jsh或替换它们ch
  • 替换每个7kcgq
  • 8f或替换每个v
  • 9p或替换每个b
  • 如有可能aehiouwxy,在任意位置添加字母以构成一个真实的英语单词。唯一的例外是,不得在之后插入
    hsc

该数字实际上可以是数字0-9的任何字符串(无小数,逗号或符号)。
该单词只能包含小写字母az。

例子

该数字32必须转换为?m?n?,其中?代表由字母组成的任何有限字符串aehiouwxy(如果愿意,则是来自免费monoid的字符串)。有许多方法,这可能做成一个真正的英文单词:manemoonyeoman等。

该数字05可以转换为?s?l??z?l?。一些可能的是easilyhasslehazel。这个词shawl是不允许的,因为h可能不能放在之后s; 它会被错误地读取为65

挑战

编写一个程序或函数,该程序或函数使用数字0-9的字符串,并找到所有可以使用简化的主系统助记符将其转换成的单词。

您的程序可以访问单词列表文本文件,该文件定义了所有“真实”英语单词是什么。此文件的每一行上都有一个小写的az字,您可以选择假定它有一个尾随的换行符。这是可用于测试的真实单词列表。您可以假设这个单词列表文件被称为f(或更长的名称)并且位于任何方便的目录中。

对于35字节的罚款(将您的分数加35),您可以假设单词列表已作为字符串列表加载到变量中。这主要用于无法读取文件的语言,但是任何提交都可以利用它。

您的程序必须输出所有单词列表中可以转换输入数字的单词。应该将它们打印到stdout(或类似格式),每行打印一次(带有可选的尾随换行符),或者如果您选择编写函数,则可以将它们作为字符串列表返回。单词列表不一定按字母顺序排列,输出也不需要。

如果没有可能的单词,则输出(或列表)将为空。如果输入空字符串,则输出也为空。

通过标准输入,命令行或函数的字符串参数获取输入。单词列表或其文件名不应是输入的一部分,而应是数字字符串。

您只匹配单词列表中的单个单词,而不匹配单词序列。该单词noon可能是的结果之一22,但单词序列no one不是。

测试用例

假设这是单词列表:

stnmrljkfp
zthnmrlshqfb
asatanamaralajakafapa
aizxydwwwnhimouooraleshhhcavabe
zdnmrlshcvb
zdnmrlshchvb
sthnmrlchgvb
shthnmrlchgvb
bob
pop
bop
bopy
boppy

输入0123456789应给出除zdnmrlshchvb和以外的所有长词shthnmrlchgvb

stnmrljkfp
zthnmrlshqfb
asatanamaralajakafapa
aizxydwwwnhimouooraleshhhcavabe
zdnmrlshcvb
sthnmrlchgvb

输入99应给出:

bob
pop
bop
bopy

(输出字可以按任何顺序排列。)

计分

以字节为单位的最短提交获胜。Tiebreaker转到第一个发布的提交。

漂亮的相关网站:numzi.com


1
您是否偶然从此视频中获得了应对这一挑战的想法?因为我其实只是昨天看了。:P
门把手

1
@Doorknob不是那个视频,而是那个家伙。几年前,我得到了他的精品课程讲座之一。他有点滑稽,但是确实很整洁。:)
卡尔文的爱好2015年

1
对于那些在现实生活中使用助记符主要系统感兴趣的人,请注意:只是声音很重要,而不是拼写。因此,“ c”在这里被列为7时,如果在单词中以“ s”音发音(例如“ ace” = 0),则实际上可以表示0。但是,我敢肯定,OP简化了挑战,因为具有完整语音功能的字典比简单的单词列表难得多。哦,23940的一个渲染是“数字”。
ErikE 2015年

@ErikE我声明我们在帖子的第二句中使用的是基于拼写的版本……
卡尔文的爱好2015年

我现在看到了,尽管我一开始确实很想念它-但在我看来,您的解释可能还不够充实,并提供了一个或两个示例。
ErikE 2015年

Answers:


6

Perl,87 84

open A,f;"@ARGV"eq s/[cs]h/j/gr=~y/stnmrljkfpzdcgqvb\0-z/0-90177789/dr&&print for<A>

将输入作为命令行参数:

$perl m.pl 23940

如果在标准输入中允许使用单词列表,则可以将其缩短一些:

$perl -lnE'INIT{$;=pop}$;eq s/[cs]h/j/gr=~y/stnmrljkfpzdcgqvba-z/0-90177789/dr&&say' 99 <f

是什么A意思open A,f
feersum 2015年

@feersum一个文件句柄,以后用于读取文件(<A>)。
nutki

4

Python 2中,215个 208字节

该Python解决方案从命令行参数索引的部分构建一个正则表达式,然后使用该(相当大的)正则表达式测试每个单词。

import re,sys
a='[sz] (d|th?) n m r l (j|sh|ch) [kcgq] [fv] [pb]'.split()
b=z='((?<![sc])h|[aeiouwxy])*'
for i in sys.argv[1]:b+=a[int(i)]+z
for d in open('f'):
 d=d.strip()
 if re.match('^'+b+'$',d):print d

缩小器之前的原始来源:

import re,sys
regexbits = '[sz] (d|th?) n m r l (j|sh|ch) [kcgq] [fv] [pb]'.split()

regex = other = '((?<![sc])h|[aeiouwxy])*'
for i in sys.argv[1] :
    regex += regexbits[int(i)] + other
print regex     # DEBUG

for word in open('f'):
    word = word.strip()
    if re.match('^'+regex+'$', word) :
        print word

例如,测试的正则表达式为99

^((?<![sc])h|[aeiouwxy])*[pb]((?<![sc])h|[aeiouwxy])*[pb]((?<![sc])h|[aeiouwxy])*$

(?<![sc])h位是“确保否定断言后面的内容”组件,可确保a h不跟随asc一般填充部分中的内容。

谢谢卡尔文。这个挑战促使我重新学习生锈的正则表达式技能。


b=c='((?<![sc])h|[aeiouwxy])*'将节省两个字节。
matsjoyce 2015年

t|th -> th?保存一个字节
Sp3000

您可以直接采用int(i)来避开地图。
xnor 2015年

感谢matsjoyce,Sp3000和xnor提供有用的高尔夫技巧。现在进行编辑,并实施建议。
逻辑骑士

2

Python 3、170

import sys,re
t=str.maketrans('sztdnmrljkcgqfvpb','00112345677778899','aehiouwxy\n')
for s in open('f'):re.sub('sh|ch','j',s).translate(t)!=sys.argv[1] or print(s,end='')

可读版本:

import sys, re

table = str.maketrans('sztdnmrljkcgqfvpb', '00112345677778899', 'aehiouwxy\n')

for line in open('f'):
    line = re.sub('sh|ch', 'j', line)
    if line.translate(table) == sys.argv[1]:
        print(line, end='')

该代码利用了一个th多余的事实(因为它映射到与t,和相同的数字h是一个填充字符)。

静态maketrans函数创建一个表,将第一个自变量的字符映射到第二个自变量的字符,并将第三个自变量的字符映射到None(这将导致这些字符被删除)。

通过将表创建为的直接参数,可以使最终代码缩短几个字节translate


您可以使用input()代替正则表达式sys.argv [1]和'[sc] h'保存几个字节。
swstephe 2015年

@swstephe。感谢您的反馈,但我认为input()不能使用它,因为它在循环内被调用。另外,建议的正则表达式的长度与我已经使用的正则表达式的长度相同(5个字节)。
ekhumoro 2015年

我在想类似“ z,t = input(),str.maketrans ...”的东西,然后只使用z而不是sys.argv。好吧,我以为我的正则表达式是4字节。
swstephe 2015年

2

sed,粘贴,grep,剪切-109

sed -e 's/[sc]h/6/g;s/[aehiouwxy]//g;y/sztdnmrljkcqgfvpb/00112345677778899/' w|paste w -|grep " $1$"|cut -f1

取一个文件“ w”,将每个单词转换为其数字,粘贴回原始单词,grep输入该数字,然后返回匹配的单词。请注意,grep后的引号后的空白是制表符,即粘贴的默认定界符。

我知道Perl遥遥领先,只是想以更好的Shell版本为例。

哦,是的,$ 1部分意味着应该从shell脚本运行(大多数shell应该可以运行),因此它需要一个命令行参数。


我当时正在考虑将我的答案转换为pure,sed以避免Perl的开放和@ARGV开销,但是缺少范围和delete函数y///会破坏它。令人惊讶的是,即使没有变量,您也可以直接在中表达逻辑本身sed。这是我的92解决方案:sed -e'h;s/[sc]h/6/g;y/sztdnmrljkcqgfvpb/00112345677778899/;s/[^0-9]*//g;T;s/^$1$//;x;t;d' f
nutki

似乎可行,为什么不回答呢?
swstephe

1

Bash + coreutils,216

sed -n "$(sed 's/[aeiouwxy]//g
:l
s/\([^sc]\)h/\1/g
tl'<w|grep -nf <(eval printf '%s\\n' `sed 's/0/{s,z}/g
s/1/{t,th,d}/g
y/2345/nmrl/
s/6/{j,sh,ch}/g
s/7/{k,c,g,q}/g
s/8/{f,v}/g
s/9/{p,b}/g'<<<$1`)|sed s/:.\*/p/)" w
  • 文件中的单词列表 w
  • 最里面的sed数字用可能的替换代替
  • eval printf使用shell括号扩展,扩大了所有可能的替换
  • sed第一行中的第二个将删除,aeiouwxy并且h(如果前面没有[sc]从单词列表中)
  • grep打印出所有匹配的行号
  • 既然我们已经剥离出来aeiouwxyh从单词列表,最后sed线匝的grep(每个匹配的行号)的结果到另一sed表达,这是由最外层的处理sed以显示来自单词表的所有可能的单词。

输出:

单词列表文件被指定为命令行arg,后跟要记忆的数字:

ubuntu@ubuntu:~$ ./numzi.sh 99
bob
pop
bop
bopy
boppy
$ ./numzi.sh 0123456789
stnmrljkfp
zthnmrlshqfb
asatanamaralajakafapa
aizxydwwwnhimouooraleshhhcavabe
zdnmrlshcvb
sthnmrlchgvb
$ 

@ Calvin'sHobbies完成。
Digital Trauma 2015年

您好像忘记了更新示例。
加尔文的兴趣爱好

-1

tr,sed,grep,xargs,sh,77

tr 0123456789 ztnmrljkfp|sed 's/ */[aehiouwxy]*/g'|xargs sh -c 'grep -x $0 f'

期望stdin中的数字和单词列表应存储在文件中f

不使用所有替换项(1将始终为z,7将始终为k),因此可以称为惰性解决方案,但它会在[1-100]中为95个数字至少找到一个助记符。


3
该问题要求您在单词列表中找到所有匹配的单词。你不能使1永远存在z7永远k。这无效。
加尔文的业余爱好

公平地说,我将删除答案。
pgy 2015年
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.