Bước tối ưu cho bảng chữ cái


30

Đưa ra một chuỗi đầu vào chỉ bao gồm các chữ cái, trả về kích thước bước dẫn đến số lượng bước tối thiểu cần thiết để truy cập tất cả các chữ cái theo thứ tự trên một bảng chữ cái gói, bắt đầu từ bất kỳ chữ cái nào.

Ví dụ, lấy từ , dog. Nếu chúng tôi sử dụng kích thước bước là 1, chúng tôi sẽ kết thúc bằng:

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

Tổng cộng có 30 bước.

Tuy nhiên, nếu chúng tôi sử dụng kích thước bước là 11, chúng tôi sẽ nhận được:

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

Tổng cộng có 6 bước. Đây là số tiền tối thiểu là bước, vì vậy kết quả lại cho doglà bước kích thước; 11.

Các trường hợp thử nghiệm:

"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

Quy tắc

  • Đầu vào sẽ là một chuỗi không rỗng hoặc mảng các ký tự bao gồm duy nhất của các chữ cái ađể z(bạn có thể lựa chọn giữa chữ hoa hoặc chữ thường)
  • Đầu ra có thể được lập chỉ mục 0 (tức là phạm vi 0-25) hoặc 1 được lập chỉ mục ( 1-26)
  • Nếu có một cà vạt, bạn có thể xuất bất kỳ kích thước bước hoặc tất cả chúng
  • Đây là , vì vậy số byte thấp nhất cho mỗi ngôn ngữ sẽ thắng!

Chúng ta có cần xử lý đầu vào trống không?
pizzapants184

1
@ pizzapants184 Không. Tôi đã cập nhật câu hỏi để chỉ định đầu vào sẽ không trống
Jo King

Chúng ta có thể lấy đầu vào như một mảng các ký tự không?
Xù xì

@Shaggy Chắc chắn bạn có thể
Jo King

Có một lý do này sử dụng chữ cái thay vì số?
Thuật sĩ lúa mì

Câu trả lời:


6

Than , 41 byte

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

Hãy thử trực tuyến! Liên kết là phiên bản dài dòng của mã. Chỉ số 0. Giải trình:

Eβ

Lặp lại các kích cỡ 26 bước. (Trên thực tế tôi lặp qua bảng chữ cái chữ thường ở đây và sử dụng biến chỉ mục.)

Eθ∧μ

Lặp lại từng ký tự của đầu vào sau đầu tiên.

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

Lặp lại 26 lần và tạo chuỗi ký tự kết quả bằng cách thực hiện 26 bước ở kích thước bước đã cho bắt đầu (được lập chỉ mục 0) với ký tự trước đó của đầu vào.

⌕...λ

Tìm vị trí của ký tự hiện tại của đầu vào trong chuỗi đó hoặc -1 nếu không tìm thấy.

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

Lấy tổng của tất cả các vị trí, trừ khi không tìm thấy vị trí nào, trong trường hợp đó sử dụng -1.

≔...θ

Tiết kiệm các khoản tiền.

⌊Φθ⊕ι

Tìm tổng không âm tối thiểu.

I⌕θ...

Tìm kích thước bước đầu tiên với tổng đó và xuất nó.


5

JavaScript, 143 byte

w=>(a=[...Array(26).keys(m=1/0)]).map(s=>~[...w].map(c=>(t+=a.find(v=>!p|(u(c,36)+~v*s-u(p,36))%26==0),p=c),p=t=0,u=parseInt)+t<m&&(m=t,n=s))|n

Hãy thử trực tuyến!

Nhờ Shaggy, sử dụng [...Array(26).keys()]tiết kiệm 9 byte.



4

Thạch , 28 26 23 byte

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

Đầu ra là 0-index. Đầu vào là một bytestring và có thể trong mọi trường hợp, nhưng chữ hoa nhanh hơn nhiều .

Đầu vào một chữ cái phải được đặt đặc biệt và có giá 2 byte. ._.

Hãy thử trực tuyến!

Lưu ý rằng đây là một cách tiếp cận vũ phu; đầu vào có bốn chữ cái trở lên sẽ hết thời gian trên TIO. Bộ kiểm tra _39 chuẩn bị cho "hiệu quả".

Làm thế nào nó hoạt động

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

Thạch , 17 byte

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

Đầu vào là một phụ của STDIN, đầu ra là 1 chỉ mục.

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

Ɠ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

JavaScript (Node.js) ,  123 121 116  114 byte

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))

Hãy thử trực tuyến!

Đã bình luận

Lưu ý : Khi cố gắng khớp một chữ cái trong bảng chữ cái với một bước nhất địnhtôi, chúng ta cần nâng cao con trỏ nhiều nhất 25lần Sau26lặp đi lặp lại không thành công, ít nhất một chữ cái phải được truy cập hai lần. Vì vậy, trình tự sẽ lặp lại mãi mãi và bức thư chúng tôi đang tìm kiếm không phải là một phần của nó. Đây là lý do tại sao chúng ta làm s[k++ >> 5]trong hàm đệ quyg, để nó từ bỏ sau 32×L lặp đi lặp lại L là độ dài của chuỗi đầu vào.

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

Ruby , 121 114 112 108 102 89 byte

->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}}}

Hãy thử trực tuyến!

Chỉ số 0. Đưa đầu vào như một mảng các ký tự.

Cảm ơn ASCII - chỉ dành cho ý tưởng chơi gôn trị giá 12 byte.


:( đóng (dựa trên giải pháp python)
ASCII chỉ có

100 , có lẽ có thể được chơi gôn nhiều hơn một chút
ASCII chỉ có


Ý tưởng tuyệt vời, thêm 1 byte bằng p,=*smẹo, nhưng tôi không chắc về tính mạnh mẽ về mặt lý thuyết của một giải pháp với số điểm phạt được mã hóa cứng ... Vì vậy, tôi đã thay đổi hằng số thành vô hạn (mặc dù giá trị của bạn sẽ cho phép giảm thêm 2 byte ).
Kirill L.

Chỉ có 2 byte, không tệ
ASCII - chỉ

3

Python 2 , 230 222 216 194 169 byte

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))

Hãy thử trực tuyến!

-22 byte từ tsh

-39 byte từ Jo King

Phiên bản cũ hơn với lời giải thích:

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))

Hãy thử trực tuyến!

Điều này sẽ ngắn hơn trong một ngôn ngữ có số lượng chữ cái chính (sẽ không cần float('inf')xử lý các vòng lặp vô hạn). Trên thực tế, bài nộp này vẫn cần điều đó để xử lý các chuỗi như "aaa". Trình này bây giờ sử dụng 26*len(s)như một giới hạn trên, dừng các vòng lặp vô hạn.

Nội dung gửi này được lập chỉ mục 0 (trả về các giá trị từ 0 đến 25).

f lấy một chuỗi (n chữ hoa) và trả về Bước Bảng chữ cái tối ưu

tlà một hàm trợ giúp lấy chuỗi và bước một bảng chữ cái và trả về số bước nhảy cần thiết để hoàn thành chuỗi (hoặc 26*len(s)nếu không thể).


2
Use while a!=A(c)and S<len(s)*26: and you may remove if a==i:return float('inf'), since len(s)*26 is upper bound of any answer.
tsh





2

Red, 197 bytes

func[s][a: collect[repeat n 26[keep #"`"+ n]]m: p: 99 a: append/dup a a m
u: find a s/1 repeat n 26[v: extract u n
d: 0 foreach c s[until[(v/(d: d + 1) = c)or(d > length? v)]]if d < m[m: d p: n]]p]

Try it online!


2

05AB1E (legacy), 33 27 26 bytes

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

Uses the legacy version because there seems to be a bug when you want to modify/use the result after a nested map in the new 05AB1E version..

0-indexed output.

Try it online or verify all test cases.

Explanation:

Ç                        # 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

Python 3, 191 178 162 bytes

Thanks everyone for all your tips! this is looking much more golflike.

*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)))

Try it online!

And my original code if anyone's interested.

Turns the word into a list of ASCII values, then iterates through step sizes 0 to 25, checking how many steps it takes to exhaust the list (there's a ceiling to stop infinite loops).

Number of steps is added to the list a.

After the big for loop, the index of the smallest value in a is printed. This is equal to the value of i (the step size) for that iteration of the loop, QED.


1
Hi & Welcome to PPCG! For starters, your posted byte count doesn't match that on TIO :) Now, for a couple of quick hints: range(26) is enough - you don't need to specify the start, since 0 is the default; a.append(n) could be a+=[n]; the first line would be shorter as map w=list(map(ord,input())), (actually with your current algorithm, in Py2 you could drop list(...) wrapping as well); avoid extra spacing/line breaks as much as possible (e.g., no need for newlines in oneliners: if p>122:p-=26)
Kirill L.

1
Also, that n>99 look suspicious, is that an arbitrary constant to break out of inifinite loop? Then it probably should be something like 26*len(w), as you never know, how large the input will be.
Kirill L.

1
BTW, you can still get rid of that list(...) in Py3 and also of one extra if: 165 bytes. Also, take a look at this tips topic, I'm sure you'll greatly improve your skills using advices from there!
Kirill L.

1
I'm not a python expert, but I think you can do while p!=c and n>len(w)*26: and get rid of that last if statement for -8 bytes.
Spitemaster

2
Although it looks terrible and goes against everything Python is, you can change n+=1 and p+=i on seperate lines to n+=1;p+=i on one.
nedla2004
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.