容易键入的单词


30

这场比赛结束了。

获胜者是CJam(22个字符),比TwiNight的答案要高一个字符。恭喜丹尼斯

值得一提的是法尔科(Falko),他对免费进口产品一无所知。


不久前,我想知道如何用诺基亚3310淘汰现代智能手机,尽管确实有一些答案,但我仍然跟不上!也许我应该采取不同的方法,根本不要写任何难以输入的单词。

如果在标准布局下,电话键盘上的同一按钮上没有两个连续的字母,我们将称其为易于键入的文本:

Telephone Keyboard


你的任务

您的任务是编写一个程序/函数,该程序可以接受s来自stdin / 的字符串作为参数,如果s可以轻松键入,则返回真实值,否则返回虚假值。输入将仅包含小写字母和空格,并且保证为非空!

计分

这是代码高尔夫,因此最少的字符数获胜。

进口报表将不会对你的最后得分进行计数,所以如果你曾经想使用std::set_symmetric_differenceliftM4itertools.combinations在你的代码,现在是时候了!

-3如果您的源代码可以轻松键入,并且假设所有不是字母的内容都位于按钮0上。毕竟,我可能想将您的代码发送给一些朋友!

测试用例

以下是一些测试用例,以检查您的代码是否按预期工作:

"x" -> True
"aardvark" -> False
"ardvark" -> True
"flonk" -> False

"im codegolfing all day long" -> False
"i indulge in minimizing bytecount" -> True

"havent heard from you in a long time" -> False
"your silence was of undue permanence" -> True

"how are  you" -> False
"how are you" -> True

打高尔夫球快乐!


连续两个空格不好吗?
Martin Ender 2014年

@MartinBüttner是的!应该为此添加一个测试用例。
Flonk 2014年

9
我有一个诺基亚dumbphone,如果我按空间的两倍,我得到一个数字0
overactor

1
相关问题:设计一种电话键盘布局,该布局基于最频繁出现的单词的可键入性来最大程度地提高得分。
justinpc 2014年

1
@jpcooper喜欢这里提到的两个吗?我使用过8pen并真的很喜欢它,除了我的电话玻璃因使用它而变热(通过接触而不是CPU活动),并且摩擦系数使它很难用于长输入。在Note 3上使用s-pen非常容易:)
Eben 2014年

Answers:


6

CJam,34 31 27 22个字符

1l{'h-_9/-D+3/X\:X^*}/

在线尝试。

运行示例

$ cjam <(echo "1l{'h-_9/-D+3/X\:X^*}/") <<< 'aardvark'; echo
0
$ cjam <(echo "1l{'h-_9/-D+3/X\:X^*}/") <<< 'ardvark'; echo
66000

怎么运行的

1l                         " Push a R := 1 and read a line L from STDIN.                  ";
                           " Initialize X := 1. (implicit)                                ";
  {                  }/    " For each character C of L, do the following:                 ";
    'h-                    "     C -= 'h'                                                 ";
       _9/-D+3/            "     Y := (C - C / 9 + 13) / 3                                ";
               X\  ^*      "     R *= X ^ Y                                               ";
                 :X        "     X := Y                                                   ";
                           " Print R. (implicit)                                          ";

背景

该代码的核心在于将映射F应用于输入字符串的每个字符C,以使同一键上的符号图像匹配。我通过观察以下内容找到了合适的地图:

映射T:C↦(C-'h')+ 13转换字符串S:=“ abcdefghijklmnopqrstuvxyz”如下:

[-59   6  7  8   9 10 11  12 13 14  15 16 17  18 19 20  21 22 23 24  25 26 27  28 29 30 31]

对于0to 的键6,将T(C)除以3就足够了,但是我们必须对stvyz中的字符进行某种校正。

映射D:C↦(C-'h')/ 9将字符串S转换为以下数组:

[ -8   0  0  0   0  0  0   0  0  0   0  0  0   0  0  0   0  1  1  1   1  1  1   1  1  1  2]

这样可以校正stvyz的商,而不会影响其他商。

最后,映射F:C↦(T(C)-D(C))/ 3转换字符串S如下:

[-17   2  2  2   3  3  3   4  4  4   5  5  5   6  6  6   7  7  7  7   8  8  8   9  9  9  9]

剩下的就是以某种方式比较连续字符。为此,我们对前一个字符的图像进行XOR F(C)-对于第一个字符,我们对前一个字符与1(变量X的默认值进行异或,然后将其与所有结果相乘。

当且仅当其中一个因子为零时(即且仅当两个连续的字符具有相同的F像)时,乘积才会为假。


我认为该字节(非字符)计数为54

@Optimizer我认为代码高尔夫球标签Wiki表示字节

此答案不再包含非ASCII字符。
丹尼斯

@professorfish标签Wiki仅是默认标签。如果挑战指定字符,则为字符。
Martin Ender 2014年

27

Python 2-80、68、64、61、58、50、48、45、44 42

即使现在变得有点荒谬,我仍将继续使用免费的库导入,甚至是__builtin__库:

from numpy import diff as D
from pprint import pprint as P
from __builtin__ import all as A
from __builtin__ import raw_input as I
from __builtin__ import bytearray as B

因此,仅以下短行计入代码长度:

P(A(D([(o-o/112-o/59)/3for o in B(I())])))

感谢Markuz提供的有关想法input()!这些自由导入的挑战总是向您介绍一些鲜为人知的库。;)


仅使用operator库的替代方法(98、83 79):

from operator import ne as n
K=[(ord(c)-1-(c>'p')-(c>'w'))/3for c in input()]
print all(map(n,K[1:],K[:-1]))

我会在这里停止。但是,你可能会进一步高尔夫使用这个版本syspprint及其他图书馆...


没有库的替代方法(105):

s=input()
n=lambda c:(ord(c)-1-(c>'p')-(c>'w'))/3
print all([n(s[i])!=n(s[i+1])for i in range(len(s)-1)])

再一次,我们在Ruby和Python中独立发布了相同的解决方案。看来这次您赢了。;)...您还不能通过分配ord(c)一个变量(例如o)然后减去c/112c/119代替布尔值来节省4个字节吗?
Martin Ender 2014年

@MartinBüttner:是的,Python有时可以击败Ruby。不幸的是,我不能lambda轻易在表达式中分配变量。随着[(o-1-o/112-o/119)/3for o in map(ord,s)]我结束了80字节再次。
Falko 2014年

啊,我明白了。病了新的进步!:D
Martin Ender 2014年

非常令人印象深刻。而且您仍然可以from sys import argv as s使用s[1]而不是input()
Markuz

实际上,input从中导入__builtin__甚至更好:D保存另一个字节。
Markuz

20

Ruby Regex(最受欢迎的风味),106 83字节

因为正则表达式

^(?!.*(  |[abc]{2}|[def]{2}|[ghi]{2}|[jkl]{2}|[mno]{2}|[p-s]{2}|[tuv]{2}|[w-z]{2}))

我刚刚削减了中间人(Ruby),并将其变成了纯正则表达式解决方案。可以使用多种样式,并且仅在字符串在同一按钮上不包含两个连续字符的情况下才找到匹配项。


您不能将它{2}放在交替之外,节省22个字节吗?
Niet the Dark Absol 2014年

1
不幸的是,@ NiettheDarkAbsol并非如此,因为这样它可以为两次重复选择不同的替代方法。
Martin Ender 2014年

嗯,当然。我知道有一个原因XD
Niet的黑暗ABSOL

荣誉是一种易于理解,易于理解的高尔夫解决方案!
GreenAsJade 2014年

12

Bash + coreutils,49岁

tr a-z $[36#8g7e9m4ddqd6]7778888|grep -Pq '(.)\1'

对于TRUE,返回退出代码1,对于FALSE,返回退出代码0:

$ for s in "x" "aardvark" "ardvark" "flonk" "im codegolfing all day long" "i indulge in minimizing bytecount" "havent heard from you in a long time" "your silence was of undue permanence" "how are  you" "how are you"; do echo "./3310.sh <<< \"$s\" returns $(./3310.sh <<< "$s"; echo $?)"; done
./3310.sh <<< "x" returns 1
./3310.sh <<< "aardvark" returns 0
./3310.sh <<< "ardvark" returns 1
./3310.sh <<< "flonk" returns 0
./3310.sh <<< "im codegolfing all day long" returns 0
./3310.sh <<< "i indulge in minimizing bytecount" returns 1
./3310.sh <<< "havent heard from you in a long time" returns 0
./3310.sh <<< "your silence was of undue permanence" returns 1
./3310.sh <<< "how are  you" returns 0
./3310.sh <<< "how are you" returns 1
$ 

非常好!在Perl中,这将是46个字符:perl -pE'y/a-z/aaadddgggjjjmmmpppptttwwww/;$_=!/(.)\1/' <(echo "x")它输出1表示“ true”,不打印“ false”。
hmatt1 2014年

@chilemagic继续并发布perl答案:)。不要忘了使用-p命令行参数(根据代码高尔夫约定)在得分上加1。
Digital Trauma 2014年

我以为我可以找到缩短时间的方法,aaadddgggjjjmmmpppptttwwww但我已经放弃了。
本杰克逊

2
@BenJackson我想出了一种方法。实际上,我们可以使用任何不同字符的字符串- 11122233344455566667778888可以。通过以36为基数对该数字的前19个数字进行编码,我们可以节省1个字符!
Digital Trauma 2014年

9

APL(Dyalog),24 23

~∨/2=/⌊¯13⌈.21-.31×⎕AV⍳⍞

∧/2≠/⌊¯13⌈.21-.31×⎕AV⍳⍞

说明

:从屏幕获取字符串输入
⎕AV:这是原子向量,基本上是APL识别的所有字符的字符串,当然包括所有小写字母(索引18〜43)和空格(索引5)
IndexOf功能。对于APL中许多需要一个或两个标量参数的函数,您可以向其提供一个代替标量的数组-APL将为您执行循环。因此返回索引的数字数组。 .21-.31×:乘以0.31,然后从0.21减去。这是一个小技巧,它将除了Z之外的相同键(尤其是PQRS)上的字母映射到相同的数字(四舍五入为整数)时,将Z映射到它自己的组
¯13⌈max-13。这会将Z带回WXY组
:向下舍入为整数
2≠/:Pairwise-。为每个连续对返回一个布尔数组。
∧/:将结果数组的所有条目与在一起。


我本来打算发布这样的内容,但是您击败了我。该死的Z键!您仍然可以通过说∧/2≠/(所有连续对都在不同的键上键入)而不是~∨/2=/(没有连续对在同一键上键入)来减少1个字符。APL FTW!
Tobia 2014年

是的,tkx。我当时在想:“我应该可以在这里刮掉1个字符,为什么我不能这样做OMGGGG!” 但是我必须去上课,所以我只发布我所拥有的。是的,DAMN Z KEY。不幸的是我在手机上,所以等到以后再编辑
TwiNight

而且我对De Morgan的法律进行了有意识的思考,但仍然无法弄清楚……多么愚蠢
TwiNight 2014年

1
祝您发短信给您的朋友。;)
Thane Brimhall 2014年

这看起来很有趣。是否可以在不购买Dyalog APL解释器的情况下尝试使用此代码?我通常使用的在线口译员似乎听不懂方言……
丹尼斯

7

Perl-44

这基本上是@DigitalTrauma 经他许可发布的答案的Perl改编。@KyleStrand减少了2个字符。

y/b-y/aadddgggjjjmmmpppptttzzz/;$_=!/(.)\1/

43个字符+ 1个-p标志。y///与相同tr///。它打印的1是true,而没有打印的是false。如果需要,我可以发布详细的解释。

示例运行:

perl -pE'y/b-y/aadddgggjjjmmmpppptttzzz/;$_=!/(.)\1/' <(echo "x")

Perl-81

$s=join"]{2}|[",qw(abc def ghi jkl mno p-s tuv w-z);say/^(?!.*(  |[$s]{2}))/?1:0

+1表示-n标志。通过使用join创建正则表达式(与Martin的正则表达式相同)来工作,该正则表达式可剃掉几个字节。

示例运行:

perl -nE'$s=join"]{2}|[",qw(abc def ghi jkl mno p-s tuv w-z);say/^(?!.*(  |[$s]{2}))/?1:0' <(echo "your silence was of undue permanence")

你能不能让被刮掉从Perl的解决方案两个字符a,并z保持untransliterated?y/b-y/aadddgggjjjmmmpppptttzzz/;$_=!/(.)\1/另外,这不会处理空格,对吗?
凯尔·斯特兰德

...oh, right, two spaces in a row is already two identical characters in a row. My bad.
Kyle Strand

@KyleStrand nice call on letting a and z remain the same. Updated answer!
hmatt1

4

JavaScript - 159 156 bytes

function g(s){p=n=-1;for(i=0;i!=s.length;i++){p=n;n=s.charCodeAt(i);n-=97;if(n>17)n--;if(n>23)n--;if(p==-1)continue;if(~~(p/3)==~~(n/3))return 0;}return 1;}

Returns 1 for truthy and 0 for falsy.

If only I could get rid of the keywords.


At least you can get rid of some whitespaces and if's :) 141 : function g(s){p=n=-1;for(i=0;i<s.length;i++){p=n;n=s.charCodeAt(i)-97;n>17&&n--;n>23&&n--;if(~p)continue;if(~(p/3)==~(n/3))return 0}return 1}
Optimizer

You use lots of interesting things in your answer that I haven't seen before. I usually write in C++ but I thought I'd give JS a shot as it's quicker to test online.
Lozzaaa

I only found this place today and thought I'd give it a shot. My next try will be superior :D
Lozzaaa

You can make your code a character shorter by replacing the != in the for loop by a <.
ProgramFOX

Yes that was in Optimizer's optimisations :) what's the etiquette on using people's suggestions in my answer? Now that there is another JavaScript entry that I can beat by accepting those modifications.
Lozzaaa

4

c, 74 bytes

main(c,d,r){for(;~(c=getchar());r*=d!=c/3,d=c/3)c-=--c/'p'*(c-'k')/7;c=r;}

Returns a non-zero exit status for TRUE and 0 for FALSE:

$ for s in "x" "aardvark" "ardvark" "flonk" "im codegolfing all day long" "i indulge in minimizing bytecount" "havent heard from you in a long time" "your silence was of undue permanence" "how are  you" "how are you"; do echo "./3310 <<< \"$s\" returns $(./3310 <<< "$s"; echo $?)"; done
./3310 <<< "x" returns 40
./3310 <<< "aardvark" returns 0
./3310 <<< "ardvark" returns 216
./3310 <<< "flonk" returns 0
./3310 <<< "im codegolfing all day long" returns 0
./3310 <<< "i indulge in minimizing bytecount" returns 72
./3310 <<< "havent heard from you in a long time" returns 0
./3310 <<< "your silence was of undue permanence" returns 232
./3310 <<< "how are  you" returns 0
./3310 <<< "how are you" returns 8
$ 

You can save 3 bytes by changing your while to for(;c=~getchar();d=c/3), and another byte by changing your first if to a ?: operator.
Allbeert

@Allbeert - Thanks. The parenthesis around c=getchar() are required though because ~ has higher precedence than =. Still, I'll take the other two bytes :)
Digital Trauma

For the last bit, does something like exit(d!=c/3); instead of if(d==c/3)exit(0); work?

@professorfish That would make the exit at that point unconditional, which I don't want
Digital Trauma

You can save one character with r*=d^c/3
Alchymist

3

Ruby 1.8, 89 83 81 78 bytes

p$*[0].chars.map{|c|c=c[0];(c-c/?p-c/?w-1)/3}.each_cons(2).map{|a,b|a!=b}.all?

Here is another submission. To my shame, it beats the regex. :(

This takes the string via command-line argument and prints a boolean.

As for the algorithm, I'm shifting down the letters after p by one and after z by two, and then I check that there are no collisions after integer division by 3.

PS: This is the first time, that using Ruby 1.8 shortened the code (due to the shorter way to get character codes).


3

Cobra - 80

def f(s)
    for c in s
        for x in 9,if' adgjmptw'[x]>c,break
        t,f=x,t<>x
    print f

3

JavaScript (ES6) 66 74

F=s=>[...s].every(c=>[...' adgjmptw'].map(x=>s+=c<x,w=s,s=0)|s!=w)

The inner loop find the group for each character. Conceptually is a 'reduce' but 'map' is shorter. The outer loop compare the group of consecutive chars and exits with false if they are equal.

Test In Firefox/Firebug console

;["x","aardvark","ardvark","flonk","im codegolfing all day long",
"i indulge in minimizing bytecount","havent heard from you in a long time",
"your silence was of undue permanence","how are  you","how are you"]
.forEach(x=>console.log(x + ' -> ' + F(x)))

Output

x -> true
aardvark -> false
ardvark -> true
flonk -> false
im codegolfing all day long -> false
i indulge in minimizing bytecount -> true
havent heard from you in a long time -> false
your silence was of undue permanence -> true
how are  you -> false
how are you -> true

You can do .some instead of every. Because even if it fails one time, the answer is falsy.
Optimizer

@Optimizer some and every are interchangeble, fiddling with the conditions. But here simply put some instead of every will not work, try it.
edc65

Hmm, you are right. I need to understand your logic first.
Optimizer

Please don't mind if I start using this [...s].every trick in my golfs :)
Optimizer

2

Perl, 83 bytes

$_=<>;chop;map{$_=ord;$_=($_-$_/112-$_/119-1)/3;die 0 if$l==$_;$l=$_}split//;die 1

Making heavy abuse of $_ in Perl.


1
As you can observe, is allowed to pass command-line parameters to the interpreter, just you have to count the extra parameters. (The bare minimum needed to access the code, -e in Perl, is free.) 71 characters alternative with command-line parameters: perl -nlaF -e 'map{$_=ord;$_=($_-$_/112-$_/119-1)/3;die 0 if$l==$_;$l=$_}@F;die 1'.
manatwork

@manatwork you don't need the -l, but it looks good!
hmatt1

@chilemagic, I just tried to reproduce the original code's equivalent, so I added -l as replacement for chop. But of course, you are right.
manatwork

Thanks @manatwork, I didn't even think to making use of the command line options for Perl.
mcreenan

2

Two tasks are tricky in Python; detecting chains, and assigning the groups. Both can be assisted using numpy, but it is not in the standard library.

Python 2 (only standard library) - 59 chars function

from itertools import imap as M
from __builtin__ import bytearray as A, all as E
from operator import ne as D, not_ as N
from re import S, sub as X, search as F

# 68
#def f(s):
# g=[(n-n/115-n/61)/3for n in A(s)]
# return E(M(D,g,g[1:]))

# 67 with regex via regex
#f=lambda s:N(F(X('(\S)(.)',r'|[\1-\2]{2}','  acdfgijlmopstvwz'),s))

# 59 slightly optimized ordinal classifier and regex sequence detector
f=lambda s:N(F(r'(.)\1',A((n-n/23-n/30)/3for n in A(s)),S))

# 69 using itertools.groupby
#from itertools import groupby as G
#from __builtin__ import sum as S, len as L
#f=lambda s:N(S(L(A(g))-1for _,g in G((n-n/115-n/61)/3for n in A(s))))

Python 2 (only standard library) - 53 chars stdin to exit value

Here I abuse the fact that issubclass(bool,int), so changing all() to any() gets me a valid exit value, shaving off the not() from the return value. The removal of function overhead made the regex versions fall behind in size.

from itertools import groupby as G, imap as M
from __builtin__ import bytearray as A, any as E
from __builtin__ import raw_input as I
from sys import exit as Q
from operator import eq as S

g=[(n-n/23-n/30)/3for n in A(I())]
Q(E(M(S,g,g[1:])))

2

J - 42 char

Function taking string on the right.

*/@(2~:/\(I.4 3 4 1,~5#3){~(u:97+i.26)&i.)

First we map the alphabet (u:97+i.26) into the numbers 0 through 25, all other characters (including spaces) going to 26 (i.). Then we map ({~) the first three elements map to the first key, the next three to the next key, and so on through the keys of the phone pad, making sure to map the space/other punctuation to a separate key at the end. (4 3 4 1,~5#3 is equal to 3 3 3 3 3 4 3 4 1 and I. turns that into a 27-item array where the first three are key 1, etc.) Then we check for pairwise inequality (2~:/\) and AND all the results together (*/).

   */@(2~:/\(I.4 3 4 1,~5#3){~(u:97+i.26)&i.) 'i indulge in minimizing bytecount'
1
   f =: */@(2~:/\(I.4 3 4 1,~5#3){~(u:97+i.26)&i.)
   f 'im codegolfing all day long'
0
   f '*/@(2~:/\(I.4 3 4 1,~5#3){~(u:97+i.26)&i.)'  NB. no -3 bonus :(
0

2

Racket, 119

(define(f t)(for*/and([s(map ~a'(abc def ghi jkl mno pqrs tuv wxyz))][i s][j s])(not(regexp-match(format"~a~a"i j)t))))

Ungolfed (combinatoric regexing):

(define(f t)
  (for*/and([s (map ~a '(abc def ghi jkl mno pqrs tuv wxyz))]
            [i s]
            [j s])
    (not (regexp-match (format "~a~a" i j) t))))

1

JavaScript - 152

Not a winner but I gave it a shot. Beats @Lozzaaa by 4 bytes as of posting time :)

function m(a){c="abc-def-ghi-jkl-mno-pqrstuv-wxyz";j=a.split("");for(z in j)if(j[z]=Math.floor(c.indexOf(j[z])/4),0!=z&&j[z-1]==j[z])return 0;return 1};

Passes all the tests.
Takes advantage of JS's lack of typing to make a multi type array, and it takes advantage of indexOf returning -1 for space support.

Usage:

m("string here")

Assumes lowercase alphabetic characters and spaces only. Returns 1 for true, 0 for false.

Maybe if I knew ES6 I could try the second challenge...


"if only ... " - Did you see my answer ? :P
Optimizer

Yes I did. I don't know ES6 (yet), sadly. However, this was interesting to make.
DankMemes

Yeah, your solution using an interesting approach.
Optimizer

1

ES6, JavaScript 89 70 characters

I know its not a winner because when coming to handy operations like getting ASCII value of character, JS puts a lot of bloat (.charCodeAt()).

N=s=>[...s].every(c=>l-(l=(c.charCodeAt()-(c>"r")-(c>"y")-1)/3|0),l=1)

Run it in Web Console of latest Firefox.

Usage:

N("testing if this works")

The function returns either true or false.

EDIT: Golfed a lot using the [...x].every trick learned from @edc65 (Thanks!)

I will try to golf it more :)


0

GML (Game Maker Language), 149

s=argument0p=n=-1for(i=0;i<string_length(s);i++){p=n;n=string_char_at(s,i)-97;x=n>17&&n--;x=n>23&&n--‌​;if(!p)x=1if(!(p/3)=!(n/3))x=0}show_message(x)

0

Python 3 - 152 chars

Not the shortest I could go, but it'll do for now

k=['abc','def','ghi','jkl','mno','pqrs','tuv','wxyz',' ']
x=input()
l=2>1
for i in range(len(x)-1):
 for j in k:
  if x[i+1] in j and x[i] in j:l=1>2
print(l)
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.