计算电话号码(包括字母)中的旋转拨号脉冲


34

在您的祖父母节那天,使用旋转式拨号拨打电话号码是这样的:

要拨出每个数字,将手指放在相应的孔中,将其拉到手指挡块上,然后松开。一种机制将使转盘旋转回到其静止位置,并且电话将断开并重新连接电路指定的次数,从而发出喀哒声。

拨数字N需要N个这样的“脉冲”,但N = 0(十个脉冲)除外。

旋转电话的特性是大数字(8、9、0)的拨号时间比小数字(1、2、3)长。这是绘制早期区号地图时的重要考虑因素,也是为什么人口稠密的纽约市(和电话线)的密度为212(仅5个脉冲),而稀疏的阿拉斯加却有907(26个脉冲)。当然,当按键式拨号变得流行时,所有这些都变得无关紧要。

挑战

用尽可能少的字节写一个程序或函数,该程序或函数将包含电话号码的字符串(或字符序列)作为输入,并输出其旋转拨号脉冲数。这些计数如下:

位数

  • 数字1-9计为该脉冲数。
  • 数字0计为10个脉冲。

字母

请注意,表盘上的数字2-9具有与之关联的拉丁字母。这些最初是用于命名交换的,但后来被重新分配给电话词和文本消息输入系统。

您必须使用E.161将字母分配给数字来支持电话号码中包含字母:

  • A,B,C = 2
  • D,E,F = 3
  • G,H,我= 4
  • J,K,L = 5
  • M,N,O = 6
  • P,Q,R,S = 7
  • T,U,V = 8
  • W,X,Y,Z = 9

您可以假定输入已经被大写或小写了。

其他字符

必须允许任意使用字符()+-./和空格作为格式分隔符。您可以选择允许任何非字母数字字符用于此目的,如果是更容易实现。

这些字符不会增加脉冲计数。

范例程式码

Python中的非查询表和函数:

PULSES = {
    '1': 1,
    '2': 2, 'A': 2, 'B': 2, 'C': 2,
    '3': 3, 'D': 3, 'E': 3, 'F': 3,
    '4': 4, 'G': 4, 'H': 4, 'I': 4,
    '5': 5, 'J': 5, 'K': 5, 'L': 5,
    '6': 6, 'M': 6, 'N': 6, 'O': 6,
    '7': 7, 'P': 7, 'Q': 7, 'R': 7, 'S': 7,
    '8': 8, 'T': 8, 'U': 8, 'V': 8,
    '9': 9, 'W': 9, 'X': 9, 'Y': 9, 'Z': 9,
    '0': 10
}

def pulse_count(phone_num):
    return sum(PULSES.get(digit, 0) for digit in phone_num)

输入和输出示例

  • 911 →11
  • 867-5309 →48
  • 713 555 0123 →42
  • +1 (212) PE6-5000 →57
  • 1-800-FLOWERS →69
  • PUZZLES →48

我假设任意ASCII标点和空格都限于通常用于电话号码(+- ()*#.)的字母和空格,就像字母限于大写字母一样。如果我错了纠正我。
亚当

1
@Adám:我已将所需的标点符号限制为仅几个常见的分隔符。它故意不包含*#,它们在按键式电话上具有特殊含义,并且不能在旋转台上拨打。
dan04

1
我们可以使用全小写而不是全大写吗?我们可以采用字符数组而不是字符串吗?
犯罪

1
我是时间旅行者!我是时间旅行者!我是时间旅行者!因为我小时候肯定使用过这样的电话,所以显然我是我自己的祖父!当我考虑时,这实际上是非常棘手的。le!
Bob Jarvis-

3
我是爷爷 我在1950年代就使用过这样的手机。当我搬到农村的一个小镇时,我发现电话公司不提供按键式服务。这是在1985年!别开玩笑了!我的祖母在客厅里有一个电话,上面有一个钩子和一个曲柄。您将听筒摘下,然后转动曲柄以获得总机操作员。设置直接拨号后,她必须更换它。
Walter Mitty

Answers:


25

05AB1E19 18 17 15字节

AÁ0ªā6+žq÷9š‡þO

在线尝试!

这是使用π的第一个答案。您可能会问为什么要使用π?好吧,这些字母按顺序与22233344455566677778889999相关联。请注意大多数数字是如何重复3次,而7则重复4次。您可以说每个数字平均重复(3 + 1/7)次。我想知道是否存在大约3 + 1/7且比22/7占用更少字节的数字…

这只给出4 7s,而不是4 9s,因此我们仍然需要处理Z作为特殊情况。

A               # alphabet (abcdefghijklmnopqrstuvwxyz)
 Á              # rotate right (zabcdefghijklmnopqrstuvwxy)
  0ª            # append 0 (zabcdefghijklmnopqrstuvwxy0)

ā6+             # range [7..33]
   žq÷          # divide by π (22233344455566677778889991010)
      9š        # prepend 9 (922233344455566677778889991010)

‡               # transliterate the implicit input with the two lists above
                # this replaces z → 9, a → 2, … y → 9, 0 → 10
 þ              # remove all non-digits
  O             # sum

为什么使用小写而不是大写?
dan04

1
@ dan04,因为05AB1E具有内置的push "abcdefghijklmnopqrstuvwxyz",但不是for的"ABCDEFGHIJKLMNOPQRSTUVWXYZ"。我可以将字母转换为大写,而不是将输入转换为小写,但这是相同的字节数。
凌晨

1
我已经对问题进行了编辑,以使您不需要前两个命令。
dan04

3
@Jonah我首先想到将范围除以常数以获得所需的序列,然后在寻找在05AB1E中表达“略大于3”的最佳方法时,我记得pi是内置的。
格林尼治标准

2
pi使用+1
Draconis

9

C#(Visual C#交互式编译器),51字节

n=>n.Sum(x=>x>64?(x-59-x/83-x/90)/3:x>47?1-~x%~9:0)

@recursive节省了1个字节

@ExpiredData的观察结果节省了10个字节,仅() +-/.会出现在输入中

在线尝试!

n =>                     // Function taking input as string
  n.Sum(x =>             // Map each value 'x' through the following
    x>64 ?               //   If 'x' is an uppercase letter
      (x-59-x/83-x/90)/3 //     Take each char's ASCII value subtracted by 59, and subtract
                         //     one if the char is 'S' and one if the char is 'Z'
    : x>47 ?             //   Else if the char is a digit
      1-~x%~9            //   Take 1 - (-x - 1) % -10 (Maps 0 to 10, and 1-9 to themselves
    : 0                  //   Else, 0
  )                      // And sum it all up, then return it

4
-10~9,应该在上下文中工作。
递归

@recursive太聪明了,谢谢
无知的体现

1
x <91检查是多余的,因为输入将仅包含()+-。//所有都小于64的空格键和数字,因此我们可以通过检查x> 64来确定字符是否为大写(因此-5个字节)
过期的数据

x <58检查也是如此,因为输入中不会包含58-64范围内的任何内容
过期数据


5

APL(Dyalog Unicode),27 字节SBCS

匿名默认前缀功能。

+/'@ADGJMPTW'∘⍸+11|(1⌽⎕D)∘⍳

在线尝试!

(… 在以下字符串中)∘⍳ 找到每个字符的ɩndex *:
   *找不到的元素,得到索引1+最大索引,即11个
⎕D  数字:"0123456789"

1⌽ 循环左移一步; "1234567890"

11| 除数除以11 *
   *所有非数字都为0
+ 将其添加到以下内容:

'@ADGJMPTW'∘⍸ 所述ɩ nterval ɩ ndex *为每个字符
  *所以[-∞, “@”)给出0, “@”, “A”)而得到1,[ “A”, “d”)给出2等
+/  总和即


5

Python 2,74个字节

lambda s:sum([(n-59-n/83-n/90)/3,1-~n%~9][n<58]for n in map(ord,s)if n>47)

在线尝试!

对每个字符的ASCII值进行一些算术运算。第一个选项检查字母,第二个选项检查数字。澄清了输入中允许的所有标点符号都是ASCII值小于48的标点符号,这使我简化了逻辑,但是现在总有一种新方法可能更好。

Python 2,84个字节

lambda s:sum(1+'1xxxx2ABCx3DEFx4GHIx5JKLx6MNOx7PQRS8TUVx9WXYZ0'.find(c)/5for c in s)

在线尝试!

使用硬编码的查找字符串,每个5个字符的块对应于给出每个值的字符(从1开始)。空格用填充x,不能在大写的输入中。幸运的是,字符串中未出现的字符会产生-1.find其总和为零。


5

JavaScript(Node.js),... 76 69字节

s=>s.replace(/\w/g,q=>w+=1/q?+q||10:parseInt(q,35)*.32-1|0||9,w=0)&&w

在线尝试!

-7感谢@Arnauld!

说明

 q |     1/q     |  +q  | parseInt(q,35)*.32 | parseInt(q,35)*.32-1|0 | Output
---+-------------+------+--------------------+------------------------+--------
 0 | Infinity(T) | 0(F) |         N/A        |           N/A          |   10
 1 |  1.0000(T)  | 1(T) |         N/A        |           N/A          |    1
 2 |  0.5000(T)  | 2(T) |         N/A        |           N/A          |    2
 3 |  0.3333(T)  | 3(T) |         N/A        |           N/A          |    3
 4 |  0.2500(T)  | 4(T) |         N/A        |           N/A          |    4
 5 |  0.2000(T)  | 5(T) |         N/A        |           N/A          |    5
 6 |  0.1666(T)  | 6(T) |         N/A        |           N/A          |    6
 7 |  0.1428(T)  | 7(T) |         N/A        |           N/A          |    7
 8 |  0.1250(T)  | 8(T) |         N/A        |           N/A          |    8
 9 |  0.1111(T)  | 9(T) |         N/A        |           N/A          |    9
 A |    NaN(F)   |  N/A |        3.20        |          2(T)          |    2
 B |    NaN(F)   |  N/A |        3.52        |          2(T)          |    2
 C |    NaN(F)   |  N/A |        3.84        |          2(T)          |    2
 D |    NaN(F)   |  N/A |        4.16        |          3(T)          |    3
 E |    NaN(F)   |  N/A |        4.48        |          3(T)          |    3
 F |    NaN(F)   |  N/A |        4.80        |          3(T)          |    3
 G |    NaN(F)   |  N/A |        5.12        |          4(T)          |    4
 H |    NaN(F)   |  N/A |        5.44        |          4(T)          |    4
 I |    NaN(F)   |  N/A |        5.76        |          4(T)          |    4
 J |    NaN(F)   |  N/A |        6.08        |          5(T)          |    5
 K |    NaN(F)   |  N/A |        6.40        |          5(T)          |    5
 L |    NaN(F)   |  N/A |        6.72        |          5(T)          |    5
 M |    NaN(F)   |  N/A |        7.04        |          6(T)          |    6
 N |    NaN(F)   |  N/A |        7.36        |          6(T)          |    6
 O |    NaN(F)   |  N/A |        7.68        |          6(T)          |    6
 P |    NaN(F)   |  N/A |        8.00        |          7(T)          |    7
 Q |    NaN(F)   |  N/A |        8.32        |          7(T)          |    7
 R |    NaN(F)   |  N/A |        8.64        |          7(T)          |    7
 S |    NaN(F)   |  N/A |        8.96        |          7(T)          |    7
 T |    NaN(F)   |  N/A |        9.28        |          8(T)          |    8
 U |    NaN(F)   |  N/A |        9.60        |          8(T)          |    8
 V |    NaN(F)   |  N/A |        9.92        |          8(T)          |    8
 W |    NaN(F)   |  N/A |       10.24        |          9(T)          |    9
 X |    NaN(F)   |  N/A |       10.56        |          9(T)          |    9
 Y |    NaN(F)   |  N/A |       10.88        |          9(T)          |    9
 Z |    NaN(F)   |  N/A |         NaN        |          0(F)          |    9

[space]().+-/不会捕获所有对象/\w/g,因此它们不会影响总数。




4

视网膜0.8.2字节

T`WTPMJGDA`Rd
}T`L`2L
0
55
\d
$*
1

在线尝试!链接包括测试用例。说明:

T`WTPMJGDA`Rd

转换字母 WTPMJGDA为数字9..0

}T`L`2L

将剩余的所有字母减1,然后重复直到所有字母都转换为数字为止。

0
55

替换055,因为他们采取相同数量的脉冲拨号的。

\d
$*
1

取数字和。


3

K4字节

解:

+/(1+(1+&(5#3),4 3 4),!10)(.Q.A,1_.Q.n,"0")?

例子:

q)k)+/(1+(1+&(5#3),4 3 4),!10)(.Q.A,1_.Q.n,"0")?"911"
11
q)k)+/(1+(1+&(5#3),4 3 4),!10)(.Q.A,1_.Q.n,"0")?"867-5309"
48
q)k)+/(1+(1+&(5#3),4 3 4),!10)(.Q.A,1_.Q.n,"0")?"+1 (212) PE6-5000"
57
q)k)+/(1+(1+&(5#3),4 3 4),!10)(.Q.A,1_.Q.n,"0")?"1-800-FLOWERS"
69

说明:

天真的方法,可能很不错。字符查找索引,查找分数,总和。

+/(1+(1+&(5#3),4 3 4),!10)(.Q.A,1_.Q.n,"0")? / the solution
                                           ? / lookup
                          (               )  / do this together
                                       "0"   / string "0"
                                      ,      / join with
                                  .Q.n       / string "0123456789"
                                1_           / drop first
                               ,             / join with
                           .Q.A              / "A..Z"
  (                      )                   / do this together
                      !10                    / range 0..9
                     ,                       / join with
     (              )                        / do this together
               4 3 4                         / list (4;3;4)
              ,                              / join with
         (5#3)                               / list (3;3;3;3;3)
        &                                    / where, creates list 0 0 0 1 1 1 2 2 etc
      1+                                     / add 1
   1+                                        / add 1
+/                                           / sum up



2

重击,256字节

您可以将(( … ))结构替换let为相同的字节数。可能存在一个很好的算法来减少案例陈述,但到目前为止还没有找到。稍作修改,您就可以使其成为一个函数(但不能以相同或更少的字节为单位,除非您可以舍弃function fname { … }顶部和尾部)。

read p;while ((${#p}>0));do case ${p:0:1} in ([1-9]) ((d+=${p:0:1}));; ([0]) ((d+=10));; ([ABC) ((d+=2));; ([P-S]) ((d+=7));; ([W-Z]) ((d+=9));;([DEF]) ((d+=3));; ([GHI]) ((d+=4));; ([JKL]) ((d+=5));; ([MNO]) ((d+=6));; (?) d=$d; esac;p=${p#?};done;echo $d

在线尝试!

使用地图字符技术的更好解决方案是使用以下tr工具:

[带有tr的重击],173个字节

read p;p=$(echo $p|tr A-Z 22233344455566677778889999);while ((${#p}>0));do case ${p:0:1} in ([1-9]) ((d+=${p:0:1}));; ([0]) ((d+=10));; (?) d=$d; esac;p=${p#?}; done;echo $d

在线尝试!


我当然想念的一种算法是在AZ上进行一些字符串替换/翻译。这样很好 我将修改以上内容以适合。
PJF

while((${#p}))工作,节省三个字节。 c=${p:0:1};case c in ([0-9]) ((d+=c?c:10));;保存另外16个。tr -dc 0-9添加到tr管道中后,您根本不需要case语句,并且可以将添加项折叠成while条件&&
天哪

感谢OMG。我不经常使用三元分配,所以我错过了。删除补码的使用也很有趣(但是假设像我的解决方案一样,忽略其他任何字符)。我设法将其read p;p=$(echo $p|tr A-Z 22233344455566677778889999|tr -dc [0-9]);while ((${#p}));do c=${p:0:1}&&((d+=c?c:10));p=${p#?};done;echo $d
压缩

1
118:p=$(head -1|tr A-Z 22233344455566677778889|tr -dc 0-9);while((${#p}));do((d+=(c=${p:0:1})?c:10));p=${p#?};done;echo $d..不需要最后三个9,因为如果第二个参数太短,tr将重用最后一个替换字符。
天哪

1
通过删除一些不必要的空格,可以将第一个示例从256减少到236。read p;while((${#p}>0));do case ${p:0:1} in ([1-9])((d+=${p:0:1}));;([0])((d+=10));;([ABC)((d+=2));;([P-S])((d+=7));;([W-Z])((d+=9));;([DEF])((d+=3));;([GHI])((d+=4));;([JKL])((d+=5));;([MNO])((d+=6));;(?)d=$d;esac;p=${p#?};done;echo $d
史蒂夫(Steve)


2

PowerShell中109 102 87字节

$(switch -r($args|% t*y){\d{$_}[A-Y]{("{0}"-f(.313*$_-18))[0]}[Z]{9}0{10}})-join'+'|iex

在线尝试!

编辑:使用@mazzy的想法进行正则表达式开关,并使用一些字符串格式来转换char-> int-> string并仅捕获第一个“数字”

原版的:

[char[]]"$args"|%{$a+=(48,(('22233344455566677778889999')[$_-65],(58,$_)[$_-ne48])[$_-lt64])[$_-gt47]-=48};$a

我希望获得小于100个字节的内容,因此我将继续研究它,看看是否还有其他事情可以做。可能有一种删除数字字符串的方法

抱歉,这很令人困惑,因为我使用布尔索引语句嵌套了数组,但是-

说明:

[char[]]"$args"|%{读取转换为字符串的输入,然后将其分解为char数组,并开始for-each循环,检查()[$_-gt47]是否()+-./输入了任何内容(所有输入的ascii字符值均小于48)
注意:Powershell接受$true$false作为10数组索引分别

然后我们得到 48符号,或者:
('22233344455566677778889999'[$_-65],(58,$_)[$_-ne48])[$_-lt64]

[$_-lt64]一个数字或字母(这里假定所有资金)检查。如果是字母,'22233344455566677778889999'[$_-65]请将其更改为0-25以索引到数组中并输出脉冲值(以char形式)。如果字符是数字,则我们看一下:(58,$_)[$_-ne48]检查0并输出,58或者只是数字char本身。

周围的一切都会在以下位置$a+= ... -=48初始化数字变量$ a0,然后添加输出。输出是数字的ascii char值,因此减去48

注意:如果输入是一个符号,我们将获得$a+=48-48,实际上忽略了它。如果它是0,我们得到$a+=58-48 +10

最后,;$a输出每个循环的最终值


您可以节省一些字节在线尝试!
mazzy

嗯,是的,我有一些额外的括号,而这=是我以前解决该问题的方法所遗留下的,谢谢!虽然,我以前没看过t*y,但您能解释一下为什么这样做能将字符串分解为字符数组吗?
正弦曲线


获得“ <100个字节”:在线尝试!:)
mazzy

-f和的好主意[0]
mazzy

2

PowerShell95 85 79字节

nwellnhof的回答启发。

灵感[0]来自正弦曲线的回答

$(switch -r($args|% t*y){\d{$_}0{10}[A-Y]{"$(.313*$_-18)"[0]}Z{9}})-join'+'|iex

在线尝试!

展开版本:

$(
    switch -r($args|% toCharArray){
        \d    {$_}
        0     {10}
        [A-Y] {"$(.313*$_-18)"[0]}
        Z     {9}
    }
)-join '+'|Invoke-Expression
key .313*$_-18 "$(...)"[0]
--- ---------- -----------
  A      2.345 2
  B      2.658 2
  C      2.971 2
  D      3.284 3
  E      3.597 3
  F      3.910 3
  G      4.223 4
  H      4.536 4
  I      4.849 4
  J      5.162 5
  K      5.475 5
  L      5.788 5
  M      6.101 6
  N      6.414 6
  O      6.727 6
  P      7.040 7
  Q      7.353 7
  R      7.666 7
  S      7.979 7
  T      8.292 8
  U      8.605 8
  V      8.918 8
  W      9.231 9
  X      9.544 9
  Y      9.857 9

1
团队合作!:D
正弦曲线



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.