최적의 알파벳 스테핑


30

문자로만 구성된 입력 문자열이 주어지면 임의의 문자에서 시작하여 랩핑 알파벳을 넘어 모든 문자를 방문하는 데 필요한 최소 단계 수를 생성하는 단계 크기를 리턴하십시오.

예를 들어,이라는 단어를 사용하십시오 dog. 단계 크기 1을 사용하면 다음과 같이 끝납니다.

defghijklmnopqrstuvwxyzabcdefg   Alphabet
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
defghijklmnopqrstuvwxyzabcdefg   Visited letters
d          o                 g   Needed letters

총 30 단계.

그러나 11 단계 크기를 사용하면 다음과 같은 결과를 얻습니다.

defghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefg
^          ^          ^          ^          ^          ^
d          o          z          k          v          g   Visited letters
d          o                                           g   Needed letters

총 6 단계. 이것은 최소 단계 수이므로 리턴 결과 dog는 단계 크기입니다. 11.

테스트 사례 :

"dog"      -> 11
"age"      -> 6
"apple"    -> 19
"alphabet" -> 9
"aaaaaaa"  -> 0 for 0 indexed, 26 for 1 indexed
"abcdefga" -> 1 or 9
"aba"      -> Any odd number except for 13
"ppcg"     -> 15
"codegolf" -> 15
"testcase" -> 9
"z"        -> Any number
"joking"   -> 19

규칙

  • 입력은 문자로 구성된 문자의 비어 있지 않은 문자열이나 배열이 될 것이다 a하는 z(대문자와 소문자를 선택할 수 있습니다)
  • 출력은 0 인덱스 (예 : 범위 0-25) 또는 1 인덱스 ( 1-26) 일 수 있습니다.
  • 동점이있는 경우 모든 스텝 크기 또는 전체를 출력 할 수 있습니다
  • 이것은 이므로 각 언어마다 가장 적은 바이트 수가 이깁니다!

빈 입력을 처리해야합니까?
pizzapants184

1
@ pizzapants184 아니요. 입력 내용이 비어 있지 않도록 질문을 업데이트했습니다
Jo King

문자 배열로 입력 할 수 있습니까?
얽히고 설킨

@Shaggy 물론 이죠
Jo King

이것이 숫자 대신 문자를 사용하는 이유가 있습니까?
밀 마법사

답변:


6

, 41 바이트

≔EEβEθ∧μ⌕⭆β§β⁺⌕β§θ⊖μ×κξλ⎇⊕⌊ιΣι⌊ιθI⌕θ⌊Φθ⊕ι

온라인으로 사용해보십시오! 링크는 자세한 버전의 코드입니다. 인덱스가 0입니다. 설명:

Eβ

26 단계 크기로 반복합니다. (실제로 여기서 소문자 알파벳을 반복하고 색인 변수를 사용합니다.)

Eθ∧μ

첫 번째 문자 다음에 입력의 각 문자를 반복합니다.

⭆β§β⁺⌕β§θ⊖μ×κξ

입력의 이전 문자로 시작하여 주어진 단계 크기 (0- 인덱싱)에서 26 단계를 수행하여 26 회 반복하고 문자열을 생성합니다.

⌕...λ

해당 문자열에서 입력의 현재 문자 위치를 찾거나 찾지 못한 경우 -1을 찾으십시오.

E...⎇⊕⌊ιΣι⌊ι

하나를 찾지 못하면 모든 위치의 합계를 취하십시오.이 경우 -1을 사용하십시오.

≔...θ

합계를 저장하십시오.

⌊Φθ⊕ι

음이 아닌 최소값을 찾으십시오.

I⌕θ...

해당 합계의 첫 번째 단계 크기를 찾아서 출력하십시오.



4

젤리 , 28 26 23 바이트

S;þḅ26ŒpṢƑƇIŻ€S:g/ƊÞḢg/

출력은 0 인덱스입니다. 입력은 바이트 열이며 어떤 경우에도 가능하지만 대문자는 많이 빠릅니다.

단일 문자 입력은 특수한 경우 2 바이트가 필요합니다. ._.

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

이것은 무차별 접근 방식입니다. 4 개 이상의 문자가있는 입력은 TIO에서 시간 초과됩니다. 테스트 스위트는 _39 "효율성"을 우선합니다 .

작동 원리

S;þḅ26ŒpṢƑƇIŻ€S:g/ƊÞḢg/  Main link. Argument: b (bytestring)

S                        Take the sum (s) of the code points in b.
 ;þ                      Concatenate table; for each k in [1, ..., s] and each c in
                         b, yield [k, c], grouping by c.
   ḅ26                   Unbase 26; map [k, c] to (26k + c).
      Œp                 Take the Cartesian product.
        ṢƑƇ              Comb by fixed sort; keep only increasing lists.
           I             Increments; take the forward differences of each list.
            Ż€           Prepend a 0 to each list.
                         I returns empty lists for single-letter input, so this is
                         required to keep g/ (reduce by GCD) from crashing.
                   Þ     Sort the lists by the link to the left.
              S:g/Ɗ      Divide the sum by the GCD.
                    Ḣ    Head; extract the first, smallest element.
                     g/  Compute the GCD.

4

젤리 , 17 바이트

ƓI%
26×þ%iþÇo!SỤḢ

입력은 STDIN의 바이트 스트링이며 출력은 1 색인입니다.

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

작동 원리

ƓI%            Helper link. Argument: m (26 when called)

Ɠ              Read a line from STDIN and eval it as Python code.
 I             Increments; take all forward differences.
  %            Take the differences modulo m.


26×þ%iþÇoSSỤḢ  Main link. No arguments.

26             Set the argument and the return value to 26.
  ×þ           Create the multiplication table of [1, ..., 26] by [1, ..., 26].
    %          Take all products modulo 26.
       Ç       Call the helper link with argument 26.
     iþ        Find the index of each integer to the right in each list to the left,
               grouping by the lists.
        o!     Replace zero indices (element not found) with 26!.
               This works for strings up to 25! = 15511210043330985984000000 chars,
               which exceeds Python's 9223372036854775807 character limit on x64.
          S    Take the sum of each column.
           Ụ   Sort the indices by their corresponding values.
            Ḣ  Head; extract the first index, which corresponds to the minimal value.

4

자바 스크립트 (Node.js를) ,  123 (121) 116  114 바이트

s=>(i=26,F=m=>i--?F((g=x=>s[p]?s[k++>>5]?j=1+g(x+i,p+=b[p]==x%26+97):m:0)(b[p=k=0]+7)>m?m:(r=i,j)):r)(b=Buffer(s))

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

댓글

NB : 알파벳 문자를 주어진 단계와 일치 시키려고 할 때나는, 포인터를 최대한 전진시켜야합니다 25타임스. 후26반복이 실패하면 하나 이상의 문자를 두 번 방문해야합니다. 따라서 시퀀스는 영원히 반복되며 우리가 찾고있는 문자는 그 일부가 아닙니다. 이것이 s[k++ >> 5]재귀 함수에서하는 이유입니다, 그래서 후에 포기 32× 반복 입력 문자열의 길이입니다.

s => (                        // main function taking the string s
  i = 26,                     // i = current step, initialized to 26
  F = m =>                    // F = recursive function taking the current minimum m
    i-- ?                     // decrement i; if i was not equal to 0:
      F(                      //   do a recursive call to F:
        (g = x =>             //     g = recursive function taking a character ID x
          s[p] ?              //       if there's still at least one letter to match:
            s[k++ >> 5] ?     //         if we've done less than 32 * s.length iterations:
              j = 1 + g(      //           add 1 to the final result and add the result of
                x + i,        //             a recursive call to g with x = x + i
                p += b[p] ==  //             increment p if
                  x % 26 + 97 //             the current letter is matching
              )               //           end of recursive call to g
            :                 //         else (we've done too many iterations):
              m               //           stop recursion and yield the current minimum
          :                   //       else (all letters have been matched):
            0                 //         stop recursion and yield 0
        )(                    //     initial call to g with p = k = 0
          b[p = k = 0] + 7    //     and x = ID of 1st letter
        ) > m ?               //     if the result is not better than the current minimum:
          m                   //       leave m unchanged
        :                     //     else:
          (r = i, j)          //       update m to j and r to i
      )                       //   end of recursive call to F
    :                         // else (i = 0):
      r                       //   stop recursion and return the final result r
)(b = Buffer(s))              // initial call to F with m = b = list of ASCII codes of s

4

루비 , 121 114 112 108 102 89 바이트

->s{(r=0..25).min_by{|l|p,=s;s.sum{|c|t=r.find{|i|(p.ord-c.ord+i*l)%26<1}||1/0.0;p=c;t}}}

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

인덱스가 0입니다. 문자 배열로 입력을받습니다.

12 바이트의 골프 아이디어를위한 ASCII 전용 덕분입니다.


:( close (파이썬 솔루션 기반)
ASCII 전용

100 , 아마도 좀 더 골프를 치기
ASCII 전용


좋은 아이디어, p,=*s트릭으로 -1 더 많은 바이트 이지만 하드 코딩 된 페널티 점수가있는 솔루션의 이론적 견고성에 대해서는 잘 모르겠습니다 ... 그래서 상수를 무한대로 변경했습니다 (값이 다른 2 바이트를 허용 할지라도) ).
Kirill L.

2 바이트 만, 나쁘지 않음
ASCII 전용

3

파이썬 (2) , 230 (222) 216 194 169 바이트

def t(s,l,S=0):
 a=ord(s[0])
 for c in s[1:]:
	while a-ord(c)and S<len(s)*26:S+=1;a=(a-65+l)%26+65
 return S
def f(s):T=[t(s,l)for l in range(26)];return T.index(min(T))

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

tsh 에서 -22 바이트

Jo King 에서 -39 바이트

설명이있는 이전 버전 :

A=map(chr,range(65,91)).index
def t(s,l,S=0):
 a=A(s[0]) 
 for c in s[1:]:
	while a!=A(c)and S<len(s)*26:
	 S+=1;a+=l;a%=26
 return S
def f(s):T=[t(s,l)for l in range(26)];return T.index(min(T))

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

이것은 소수의 문자를 가진 언어에서 더 짧을 것 float('inf')입니다 (무한 루프를 처리 할 필요가 없습니다 ). 실제로이 제출은 "aaa"와 같은 문자열을 처리하기 위해 여전히 필요합니다.이 제출은 이제26*len(s) 상한으로 되어 무한 루프를 중지합니다.

이 제출물은 0으로 색인화됩니다 (0에서 25까지의 값을 리턴 함).

f (n 대문자) 문자열을 가져와 최적의 알파벳 스테핑을 반환합니다.

t문자열과 알파벳 스테핑을 사용하고 문자열을 완성하는 데 필요한 홉 수를 반환하는 (또는 26*len(s)불가능한 경우) 도우미 함수입니다 .


2
사용 while a!=A(c)and S<len(s)*26:하면 제거 할 수 if a==i:return float('inf')있기 때문에, len(s)*26상위 어떤 대답의 바인딩됩니다.
tsh






2

05AB1E (레거시) , 33 27 26 바이트

Ç¥ε₂%U₂L<©ε®*₂%Xk'-žm:]øOWk

새 05AB1E 버전에서 중첩 된 맵 이후 결과를 수정 / 사용하려는 경우 버그가있는 것으로 보이므로 레거시 버전을 사용합니다.

인덱스가 0 인 출력.

온라인으로 사용해보십시오 하거나 모든 테스트 사례를 확인하십시오 .

설명:

Ç                        # ASCII values of the (implicit) input
 ¥                       # Deltas (differences between each pair)
  ε                      # Map each delta to:
   ₂%                    #  Take modulo-26 of the delta
     U                   #  Pop and store it in variable `X`
      L<                #  Push a list in the range [0,25]
         ©               #  Store it in the register (without popping)
          ε              #  Map each `y` to:
           ®*            #   Multiply each `y` by the list [0,25] of the register
             ₂%          #   And take modulo-26
                         #   (We now have a list of size 26 in steps of `y` modulo-26)
               Xk        #   Get the index of `X` in this inner list (-1 if not found)
                 '-₄:   '#   Replace the minus sign with "1000"
                         #   (so -1 becomes 10001; others remain unchanged) 
]                        # Close both maps
 ø                       # Zip; swapping rows/columns
  O                      # Sum each
   W                     # Get the smallest one (without popping the list)
    k                    # Get the index of this smallest value in the list
                         # (and output the result implicitly)

2

파이썬 3 , 191 (178) 162 바이트

모든 팁을 주셔서 감사합니다. 이것은 훨씬 더 골프처럼 보입니다.

*w,=map(ord,input())
a=[]
for i in range(26):
 n=1;p=w[0]
 for c in w:
  while n<len(w)*26and p!=c:
   n+=1;p+=i;
   if p>122:p-=26
 a+=[n]
print(a.index(min(a)))

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

그리고 내 원래 코드관심이 있다면 .

단어를 ASCII 값 목록으로 변환 한 다음 0에서 25까지의 단계 크기를 반복하여 목록을 소진하는 데 걸리는 단계 수를 확인합니다 (무한 루프를 중지하기 위해 천장이 있음).

단계의 수는 목록에 추가됩니다 .

큰 for 루프 후에는 a 에서 가장 작은 값의 인덱스 가 인쇄됩니다. 이는 루프 QED 반복에 대한 i 값 (단계 크기) 과 같습니다 .


1
PPCG에 오신 것을 환영합니다! 우선, 게시 된 바이트 수는 TIO와 일치하지 않습니다 :) 이제 몇 가지 빠른 힌트 : range(26)충분합니다-0이 기본값이므로 시작을 지정할 필요가 없습니다. a.append(n)될 수있다 a+=[n]; 첫 번째 줄은 map으로 짧습니다 w=list(map(ord,input()))(실제로 현재 알고리즘을 사용하면 Py2에서는 list(...)줄 바꿈도 가능합니다). 가능한 한 여분의 간격 / 줄 바꿈을 피하십시오 (예 : oneliners에 줄 바꿈이 필요 없음 if p>122:p-=26)
Kirill L.

1
또한, n>99의심스러운 것처럼 보입니다. 무한 루프에서 벗어날 수있는 임의의 상수입니까? 그렇다면 아마도 26 * len (w)와 같을 것입니다. 아시다시피 입력의 크기는 얼마입니까?
Kirill L.

1
BTW, 당신은 여전히 list(...)Py3에서 그것을 제거 할 수 있으며 하나의 추가 if: 165 바이트 . 또한이 팁 주제를 살펴보십시오. 여기서 조언 을 사용하여 기술을 크게 향상시킬 것입니다!
Kirill L.

1
나는 파이썬 전문가는 아니지만 while p!=c and n>len(w)*26:-8 바이트에 대한 마지막 if 문을 제거하고 제거 할 수 있다고 생각합니다 .
Spitemaster

2
그것은 끔찍와 파이썬이 모든 것을 거스르는 있지만 변경할 수 있습니다 n+=1p+=i에 별도의 라인 n+=1;p+=i하나.
nedla2004
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.