이것을 몇 번 눌러야합니까?


24

우리는 모두 구식 전화 키패드에 익숙합니까? 참고로 다음과 같습니다.

Telephone Keybad


소문자 ASCII 문자와 단일 공백 으로 만 구성된 문자열이 주어진 경우 전화 키패드로 전체 문자열을 위와 같이 입력하려면 탭 수를 반환해야합니다.

이에 익숙하지 않은 사람들을 위해 다음과 같이 작동합니다.

  • 2예를 들어, 숫자가있는 키 에는 문자열이 abc적혀 있습니다. 을 입력 a하려면이 키를 한 번 b눌러야합니다. 두 번 c눌러야하고 세 번 눌러야합니다.

  • 동일한 키에있는 연속 문자의 경우 1 초 후에 다시 눌러야합니다. 따라서을 입력 cb하려면을 3 번 누르고 c잠시 기다린 다음을 두 번 눌러 b5 번 탭해야합니다.

  • 번만 누르면되는 단일 공백을 제외하고 다른 모든 키에도 동일하게 적용됩니다 . 또한 열쇠 79네 글자가 있습니다. 동일한 알고리즘이 적용되며 문자의 수만 다릅니다. 각 키에 해당하는 문자열은 위의 이미지 (소문자) 또는 다음 목록에서 찾을 수있는 모든 문자가 포함되어 있습니다.

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

테스트 사례

입력-> 출력 (설명)

""-> 0 (아무것도 탭하지 않아야 함)
"물"-> 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 규칙 및 기본 허점이 적용됩니다.

  • 언어의 기본 문자열 유형으로 만 입력 할 수 있습니다. 출력은 정수 또는 해당 정수의 문자열 표현 일 수 있습니다.

  • 이것은 이며 모든 언어에서 가장 짧은 답변 입니다 .




2
나는 당신이 초당 1 탭을하고 1 초를 기다려야하고 탭 대신 를 세면 이것이 더 흥미로운 질문이라고 생각합니다 .
Yakk

@Yakk 너무 복잡 할 것입니다
Mr. Xcoder

@ Mr.Xcoder 확실합니까? 여기 코드 마법사는 트윗보다 적은 공간에서 불가능한 작업을 수행하는 것을 보았습니다.
J_F_B_M

답변:


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)&&t71 바이트 동안
Johan Karlsson

고마워, @JohanKarlsson, 나는 샤워하는 동안 같은 것을 상상했다! 5 바이트를 더 줄일 수있는 다른 최적화 방법을 찾았습니다.
Rick Hitchcock

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.
Neil

1
@Neil은 더 짧지는 않지만 확실히 더 똑똑합니다.
Rick Hitchcock

1
@Neil 게시해야합니다.
Mr. Xcoder 2016 년

7

05AB1E , 29 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이 표시됩니다. 다른 곳에서도 문제가 없습니다
Mr. Xcoder

@ Mr.Xcoder : 빈 문자열은 출력을 제공하지 않지만 여전히 잘못되었습니다. 알려 주셔서 감사합니다. 수정하겠습니다.
Emigna 2016 년

2
TIO에 10을줍니다.
Mr. Xcoder 2016 년

@ Mr.Xcoder : 네 빈 문자열을 명시 적으로 제공해야합니다. 빈 문자열과 다른 입력이 없습니다. 내가 아는 약간 혼란 스럽습니다. 지금 수정 :)
Emigna

@ Mr.Xcoder : 빈 문자열 입력은 다음과 같습니다
Emigna

7

파이썬 2 , 56 바이트

@RickHitchcock의 Javascript 솔루션 과 동일한 알고리즘을 사용합니다.

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

온라인으로 사용해보십시오!


재미있는 해결책. 공백으로 어떻게 작동합니까?>. <?
Mr. Xcoder 2016 년

문자열에없는 것은 @ Mr.Xcoder가 '...'.find(c)반환합니다 -1. 2를 추가하면 키를 한 번 누를 수 있습니다.
ovs 2016 년

나는 그것이 돌아 왔다는 것을 알았지 만 -1, 당신이 +2상용구 를 가지고 있다는 것을 몰랐습니다 ... 어쨌든, 가장 짧은 파이썬 솔루션.
Mr. Xcoder 2016 년

내가 :) 당신이 그것을 게시 :( 좋은 일을뿐만 아니라이 솔루션을 찾기 위해 실현 될 때까지 OML, 나는 천천히 내 프로그램 다운 골프 후 동일한 솔루션을 만드는 일이
마리오 Ishac에게


5

Dyalog APL, 37 바이트

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

온라인으로 사용해보십시오!

방법?

가져 오기 문자열에 입력의 모든 문자의 ndex을 'adgjmptw behknqux~cfilorvy~'( sz28로 기본 설정됩니다) 9 라운드까지와 합으로, 나누기.


'adgjmptw ' 'behknqux' 'cfilorvy' 'sz'바이트를 절약 하는 데 사용할 수 있습니다
Kritixi Lithos


@LeakyNun onice
Uriel

줄에 공백을 넣을 수 있습니다
Kritixi Lithos

@Uriel 대기, 당신은 계산할 필요가 f←없으므로 47 바이트입니다
Leaky Nun

4

자바 스크립트 (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의 공식을 이해하지 못해서 내 자신을 생각해 냈습니다.


순수 산술 :)
Mr. Xcoder

어떻게하지 s=>[...s]하지 왜 그냥s=>s.map()...
에반 캐롤

1
@EvanCarroll s은 문자열이므로 map직접 사용할 수 없습니다 . ...s반복을 배열로 변환 s하면서 [...s]효과적으로 s문자 배열로 분할 합니다.
Neil

4

기음, 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
TAS

힌트를 주셔서 감사합니다. s나중에 사용하기 때문에 for 루프에 넣을 수 없었지만 int선언을 함께 넣고 필요한 곳에 할당자를 사용했습니다.
dbuchmann

예, 동료 C 골퍼! 어쨌든 일부 포인터 : for 루프는 거의 모든 상황에서 while 루프보다 엄격하게 좋습니다. 반복 식에서 특히 자유 세미콜론을 활용하십시오. 대부분의 장소에서 세미콜론 대신 쉼표를 사용하면 대부분의 장소에서 중괄호가없는 상태에서 벗어날 수 있습니다. 다른 최적화가 있지만 컴파일하는 C 버전에 더 의존합니다.
dj0wns

4

하스켈 -74 71 62 바이트

편집 : 필터 대신 목록 이해를 사용하여 3 바이트 제거

편집 : Siracusa, Laikoni 및 Zgarb 덕분에 9 바이트를 절약하십시오!

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

용법

λ> f "candela"
13
λ>

온라인으로 사용해보십시오!


중복 문자의 목적은 무엇입니까?
Mr. Xcoder 2016 년

@ Mr.Xcoder 탭 수를 계산하는 데 사용되며 설명을 추가합니다.
Henry

당신은 다시 작성하여 하나의 바이트를 저장할 수 ff=length.(=<<)(\x->x:[y|y<-l,y==x])어디 (=<<)이며 concatMap여기.
siracusa

또 다른 하나는 다음으로 돌아갑니다 filter.f=length.(=<<)(\x->x:filter(==x)l)
siracusa

1
l한 번만 사용 하면 인라인 될 수 있습니다.
Laikoni


3

클로저, 82 76 바이트

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

오, 그것은 단지에 간단 filter하고 count사용하는 것보다 frequencies. 기발한:

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

문자열은 주어진 문자의 키를 한 번만 몇 번 이상 인코딩 하는지를 인코딩합니다. :)





2

자바, 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에게 감사합니다 ( a유형은 String). 95 바이트는 73 바이트가되었습니다!

람다 식은을 사용하여 각 문자의 프레스 수를 요약합니다 map(). map()이 수학을 사용하여 스트림의 각 문자 (소문자 범위의 ASCII는 97-122 임)를 적절한 값으로 변환합니다 (단순 톱파처럼 보이지만 두 사이클을 모두 고려하는 것은 성가시다) 1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112). 다음 은 해당 모델의 데스 모 그래프입니다.


허점 목록은 지금까지 모든 사람들이 그렇게 한 것처럼 보이지만 코드 스 니펫을 게시하지 말라고 말합니다. 어느 쪽이든, 내 전체 프로그램은 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에서는 람다를 사용할 수 있습니다. 따라서이 경우 a->{return a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum();}허용됩니다. 그리고 그것은 단일 반환 진술이기 때문에 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
람다에 대해 알아야 할 사항. f=세미콜론을 세거나 세지 않아도됩니다 ;. 그리고 당신은 또한 당신이 유형이 무엇인지 언급 (그래서 대신만큼 매개 변수의 유형을 추가 할 필요가 없습니다 (String a)->당신이 사용할 수있는 a->그 입력이 언급 aA는 String답변에서). 아, 아직 Java 를 사용하지 않는 경우의 <모든 언어>를 사용하는 방법 은 흥미 롭습니다.
Kevin Cruijssen

1

수학, 83 바이트

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

Mathematica 답변은이 함수의 입력과 같은 문자열 변수에 대한 문자 목록을 사용할 수있는 것으로 일반적으로 인정되는 것 같습니다. (또한 a시작 부분에 누락이 "bc1..."있습니까?)
Greg Martin

이것은 코드 골프입니다. 이것은 "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는 합계를 수행합니다.


당신의 기계에 당신이 필요할지도 모릅니다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=ns로컬 이기 때문에 작동하지 않습니다 . 에 비트 *s=n만 있기 때문에 작동 하지 않습니다. 일부 메시지에는 충분하지 않습니다. 하지만 당신은에 대해 옳습니다 . 감사. CHAR_BIT*ss++
Ray

1

APL (Dyalog) , 36 바이트

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

온라인으로 사용해보십시오!

SZ가 없는 알파벳에서 mod-3 인덱스를 찾습니다 . 우주부터 SZ 를 찾을 수 없으므로 인덱스 25 (최대 인덱스보다 하나 이상)가 " "에있어 "공간"에 적합합니다. 그런 다음 각 S 또는 Z에 3을 추가하면 됩니다.

{ 인수가 로 표시되는 익명 함수 :

⎕A~'SZ' 대문자 ASZ를 제외한 lphabet

819⌶ 소문자

⍵⍳⍨ 그 주장의 요점은

¯1+ 부정적인 것을 추가하다

3| 모드 -3

1+ 하나를 추가하십시오 (이것은 모든 0 모드를 3으로 변환합니다)

(),  접두사 :

  ⍵∊'sz' 인수가 s 또는 z 인 부울

   3을 곱하다

+/ 합집합



1

Pip, 100 90 bytes

a:qb:["abc""def""ghi""jkl""mno""pqrs""tuv""wxyz"s]Fc,#a{Fd,#b{e:((bd)@?(ac))e<4?i+:e+1x}}i

Check each character of the input for a match in each element of b. The index of that match plus 1 gets added to the total.

Try it online!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.