我应该按几次?


24

我们都习惯了老式的电话键盘,对吗?供参考,如下所示:

电话Keybad


给定一个仅包含小写ASCII字母和单个空格的字符串,您的任务是返回一个敲击次数,以便使用上面的电话键盘键入完整的字符串。

对于不熟悉此功能的人,以下是它的工作原理:

  • 2例如,带有数字的键也记录有字符串abc。要键入a,必须按一次此键,因为b必须按两次,并且c必须按三次。

  • 对于同一键上的连续字母,必须等待1秒钟再按一次。因此,如果要键入cb,则必须按3次c,等待一秒钟,然后按两次b,因此仍需点击5次。

  • 除一个空格仅需按1 外,其他所有键也是如此。另请注意,键7和上9有四个字母。应用相同的算法,唯一的区别是字母数。可以在上图(但小写)或以下列表中找到与每个键对应的字符串,其中包含您可能会收到的所有字符:

    "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz", " "
    

测试用例

输入->输出(说明)

“”-> 0(不要轻敲)
“ water”-> 8(“ w,a,t”分别需要敲击1次(在键9、2和8上),“ e”需要2次敲击(在3号键上),“ r”需要3次敲击(在7号键上) ),1 + 1 + 1 + 2 + 3 = 8)
“肥皂”-> 9(4 + 3 + 1 + 1)
“坎德拉”-> 13(3 + 1 + 2 + 1 + 2 + 3 + 1)
“代码高尔夫”-> 20(3 + 3 + 1 + 2 + 1(用于空格)+ 1 + 3 + 3 + 3)
“山丘之王”-> 33(2 + 3 + 2 + 1 + 1 + 3 + 3 + 1 + 1 + 2 + 2 + 1 + 2 + 3 + 3 + 3)

眼镜

  • 适用标准I / O规则和默认漏洞。

  • 您只能以您的语言的本机String类型进行输入。输出可以是整数,也可以是该整数的字符串表示形式。

  • 这是,是每种语言中最短的答案。




2
我认为如果您每秒进行1次点击,并且必须等待1秒,然后计算秒数而不是点击,这将是一个更有趣的问题。
Yakk

@Yakk那太复杂了
Xcoder先生17年

@ Mr.Xcoder您确定吗?我已经看到这里的代码向导在比tweet更少的空间中完成了不可能的工作。
J_F_B_M

Answers:


11

JavaScript(ES6)77 66 64 60字节

(由于@Johan Karlsson和@Arnauld节省了一些字节)。

s=>[...s].map(l=>s=~~s+2+'behknquxcfilorvysz'.search(l)/8)|s


(s,t=0)=>[...s].map(l=>t+=(1+'behknquxcfilorvysz'.indexOf(l)/8|0)+1)&&t为71个字节
Johan Karlsson

谢谢,@ JohanKarlsson,我在洗澡时发现了同样的事情!找到另一种优化方法以节省5个字节。
里克·希区柯克

6
我找到了71个字节的纯算术解决方案:f=s=>[...s].map(c=>t+=((c=parseInt(0+c,36))>23?c+3:c&&~-c%3)%7%4+1,t=0)|t
尼尔

1
@Neil,虽然可能不会更短,但是肯定更聪明。
里克·希区柯克

1
@Neil您应该发布它。
Xcoder先生17年

7

05AB1E29 26 25字节

ð¢svA•22ā₂•S£ð«øðδKy.åƶOO

在线尝试!

说明

ð¢                         # count spaces in input
  sv                       # for each char y in input
    A                      # push the lowercase alphabet
     •22ā₂•S               # push the base-10 digit list [3,3,3,3,3,4,3,4]
            £              # split the alphabet into pieces of these sizes
             ð«            # append a space to each
               ø           # transpose
                ðδK        # deep remove spaces
                   y.å     # check y for membership of each
                      ƶ    # lift each by their index in the list
                       O   # sum the list
                        O  # sum the stack

抱歉,如果输入为空,则为10。其他情况都很好
Xcoder先生17年

@ Mr.Xcoder:空字符串不提供任何输出,但这仍然是错误的。感谢您的通知,我会解决。
Emigna

2
它在TIO上给出10。
Xcoder先生17年

@ Mr.Xcoder:是的,您必须明确给出空字符串。没有输入与空字符串不同。我知道这有点令人困惑。现在已修复:)
Emigna

@ Mr.Xcoder:像这样
Emigna

7

Python 2,56个字节

使用与@RickHitchcock的Javascript解决方案相同的算法

lambda x:sum('behknquxcfilorvysz'.find(c)/8+2for c in x)

在线尝试!


有趣的解决方案。它如何处理空格,我不明白>。<?
Xcoder先生17年

@ Mr.Xcoder '...'.find(c)返回字符串中未包含的任何内容-1。通过加2,我们得到一键按下。
ovs

我知道它返回了-1,但是没有意识到您有一个+2样板...无论如何,这是迄今为止最短的Python解决方案。
Xcoder先生17年

Oml,在慢慢打好我的程序后,我碰巧做出了完全相同的解决方案,直到我意识到您也发布了它:(找到这个解决方案也很不错:)
Mario Ishac


5

Dyalog APL,37个字节

+/⌈9÷⍨'adgjmptw behknqux~cfilorvy~'⍳⍞

在线尝试!

怎么样?

获取输入的每一个字符的ndex字符串中'adgjmptw behknqux~cfilorvy~'sz将默认为28)9,圆起来总和,除以。


您可以'adgjmptw ' 'behknqux' 'cfilorvy' 'sz'用来保存一些字节
Kritixi Lithos


@LeakyNun onice
Uriel

您可以在字符串中放置空格
Kritixi Lithos

@Uriel等待,您无需计数,f←因此为47字节
Leaky Nun

4

JavaScript(ES6),71个字节

f=
s=>[...s].map(c=>t+=((c=parseInt(0+c,36))>23?c+3:c&&~-c%3)%7%4+1,t=0)|t
<input oninput=o.textContent=f(this.value)><pre id=o>

看没有字母表!我不太了解@LeakyNun的公式,所以我想出了自己的公式。


纯算术:)
Xcoder先生,2017年

为什么不s=>[...s]做些什么s=>s.map()...
Evan Carroll

1
@EvanCarroll s是字符串,因此您不能map直接使用它。...s迭代s,同时[...s]将迭代转换为数组,有效地拆分s为字符数组。
尼尔

4

C, 211 196字节

第一次提交在这里...看起来很长,我看到这不是一种有效的方法,但至少有效:)

f(char*n){char*k=" abcdefghijklmnopqrstuvwxyz";int t[]={0,3,3,3,3,3,4,3,4};int l=0,s,j,i;while(*n){i=0;while(k[i]){if(k[i]==*n){s=0;for(j=0;s<i-t[j];s+=t[j++]);*n++;l+=(!i?1:i-s);}i++;}}return l;}

非高尔夫版本:

int f(char *n){
  char *k=" abcdefghijklmnopqrstuvwxyz";
  int t[]={0,3,3,3,3,3,4,3,4};
  int l=0,s,j,i;
  while(*n){                          // loop through input characters
    i=0;
    while(k[i]){
      if(k[i]==*n){                   // find matching char in k
        s=0;
        for(j=0;s<i-t[j];s+=t[j++]);  // sum up the "key sizes" up to the key found
        *n++;
        l+=(!i?1:i-s);                // key presses are i-s except for space (1)
      }
      i++;
    }
  }
  return l;
}

*(k+i)可以k[i]
CalculatorFeline

您可以剪切一个后面的空格*(如char*n),并添加您的声明,以你的空for声明(而不是int s=0,j=0;(for(;你有for(int s=0,k=0;)和替代i==0使用!i
泰斯

谢谢您的提示。我无法放入sfor循环,因为稍后会用到它,但是我将int声明放在一起,并在需要的地方使用了Assignemts。
dbuchmann

是的,是C级高尔夫球手!无论如何,有些指针:在几乎所有情况下,for循环都比while循环严格地更好-充分利用自由分号,尤其是在迭代表达式中。在大多数情况下,请使用逗号而不是分号,这样一来,大多数情况下就不会使用花括号了。还有其他优化,但是它们更依赖于要编译到的C版本。
dj0wns

4

Haskell- 74 71 62字节

编辑:通过使用列表理解而不是过滤器删除了3个字节

编辑:感谢Siracusa,Laikoni和Zgarb,节省了9个字节!

f=sum.(>>= \x->1:[1|y<-"bcceffhiikllnooqrrsssuvvxyyzzz",y==x])

用法

λ> f "candela"
13
λ>

在线尝试!


重复信件的目的是什么?
Xcoder先生17年

@ Mr.Xcoder用于计数抽头,我将添加一个解释。
亨利

您可以通过重写保存一个字节ff=length.(=<<)(\x->x:[y|y<-l,y==x]),这里(=<<)concatMap在这里。
siracusa

另一个要回到filterf=length.(=<<)(\x->x:filter(==x)l)
siracusa

1
由于l只使用一次,因此可以内联。
Laikoni


3

Clojure,82 76字节

#(apply +(for[c %](+(count(filter #{c}"bcceffhiikllnooqrrsssuvvxyyzzz"))1)))

哦,这是简单的,只是filtercount比使用frequencies。原版的:

#(apply +(count %)(for[c %](get(frequencies"bcceffhiikllnooqrrsssuvvxyyzzz")c 0)))

该字符串比给定字符按一次键编码的次数多得多:)



2

Python 3个字节

可能不是最佳选择,因为这是我有史以来第一次使用Python打高尔夫球。

lambda x:sum((ord(i)-8)%3.15//1+3*(i>'y')+(i>' ')for i in x)

在线尝试!



2

Java,95 73字节

a->a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum()

感谢Kevin Cruijssen使该函数成为lambda表达式(a类型为String)。95字节变为73字节!

Lambda表达式使用来汇总每个字符的按下次数map()map()使用以下数学运算将流中的每个字符(小写的ASCII码为97-122)转换为适当的值(看起来像简单的锯齿波,但同时考虑到这4个循环很烦人)1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)是该模型的desmos图。


漏洞列表说即使到目前为止看起来每个人都这样做,但不要发布代码片段。无论哪种方式,我的完整程序都是130个字节。在这里是:interface Z{static void main(String a){System.out.print(a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum());}}
亚当·门登霍尔

1
欢迎来到PPCG!确实,不允许使用摘要,但默认值为program或function。借助Java 8,您可以使用lambda。因此在这种情况下a->{return a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum();}是允许的。并且由于它是单个return语句,所以a->a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum()73个字节)将是您的答案。另外,这是您可能想要添加到答案中的TryItOnline链接。再说一遍:欢迎,很好的答案。向我+1。
凯文·克鲁伊森

2
有关lambda的一些注意事项。您不必算数,f=也不用引号引起来;。而且,只要您提及参数的类型,您也不必添加参数的类型(因此,(String a)->您可以使用a->并提及输入aString答案中的“ a”)。哦,如果您还没有阅读过Java高尔夫技巧<all language>高尔夫技巧,可能会很有趣。
凯文·克鲁伊森

1

Mathematica,83个字节

c=Characters;Tr[Tr@Mod[c@"bc1def1ghi1jkl1mno1pqrstuv1wxyz "~Position~#,4]+1&/@c@#]&

人们似乎普遍认为,允许Mathematica答案使用字符串列表的字符列表,例如此函数的输入。(也在a开始时缺少"bc1..."吗?)
Greg Martin

这是代码golf。这没有给出正确的结果。“ Tr”完成了这项工作
J42161217

1

QBIC,94字节

[_l;||_SA,a,1|p=p-(instr(@sz`,B)>0)-(instr(@cfilorvy`+C,B)>0)-(instr(@behknqux`+C+D,B)>0)+1}?p

说明

[    |      FOR a = 1 TO
 _l |         the length of
   ;            the input string (A$)
_SA,a,1|    Take the a'th char of A$ and assign it to B$
p=p         p is our tap-counter, and in each iteration it gets increased by the code below
            which consist of this pattern:
                instr(@xyz`,B)>0    where 
                - instr tests if arg 2 is in arg 1 (it either returns 0 or X where X is the index of a2 in a1)
                - @...` defines the letters we want to test as arg1
                - B is the current letter to count the taps for
            Each of these blocks adds 1 tap to the counter, and each block has the letters of its level
            (4-taps, 3-taps or 2-taps) and the level 'above' it.
    -(instr(@sz`,B)>0)              <-- letters that require 4 taps
    -(instr(@cfilorvy`+C,B)>0)      <-- 3 or 4 taps
    -(instr(@behknqux`+C+D,B)>0)    <-- 2, 3,or 4 taps
    +1                              <-- and always a 1-tap
}           NEXT
?p          PRINT the number of taps

1

69 68个字节

bc<<<`fold -1|tr "\n "adgjmptwbehknquxcfilorvysz +[1*9][2*8][3*8]44`

在线尝试!

每行折叠一个字符,用+,每个空格 1和每个字母对应的推入次数对每个换行符进行音译。公元前求和。


在您的机器上,您可能需要bc <(fold -1|tr "\n "adgjmptwbehknquxcfilorvysz +[1*9][2*8][3*8]44;echo 0)
marcosm

1

C,92 88字节

c,n;f(char*s){n=0;while(c=*s++)n+=(c=='s')+3*(c>'y')+1+(c+1+(c<'s'))%3-(c<33);return n;}

您可以使用s=n替换return n,并结合s++;c=*s。它可以短9个字节。
Keyu Gan

@KeyuGan s=n不起作用,因为s它是本地的。而且*s=n由于中仅包含CHAR_BIT*s,因此对某些消息来说是不够的,因此无法使用。但是你是对的s++。谢谢。

1

APL(Dyalog),36字节

{+/(3×⍵∊'sz'),1+31+⍵⍳⍨819⌶⎕A~'SZ'}

在线尝试!

查找字母中不包含SZ的mod-3索引。由于未找到空间SZ,因此它们“具有”索引25(比最大索引大1),这对空间很有用。然后我们只需要为每个SZ加3 。

{ 以represented表示参数的匿名函数:

⎕A~'SZ' 大写字母A字母,SZ除外

819⌶ 小写

⍵⍳⍨ 该ɩ的说法在ndices

¯1+ 加负数

3| mod-3

1+ 加一(这会将所有0-mod转换为3)

(), 前置:

  ⍵∊'sz' 布尔值,其中参数为sz

   乘以3

+/ 和



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.