最佳字母步进


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

规则

  • 输入将只包含字母字符的非空字符串或数组az(你可以大写或小写之间进行选择)
  • 输出可以是0索引(即范围0-25)或1索引(1-26
  • 如果有平局,您可以输出任何步长或全部
  • 这是,因此每种语言的最低字节数为准!

我们需要处理空输入吗?
pizzapant184

1
@ pizzapants184号我已经更新的问题指定输入将非空
乔金

我们可以将输入作为字符数组吗?
毛茸茸的

@Shaggy确保可以
Jo King

是否有理由使用字母而不是数字?
小麦巫师

Answers:


6

木炭,41字节

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

在线尝试!链接是详细版本的代码。0索引。说明:

Eβ

循环显示26个步长。(实际上,我在这里循环使用小写字母并使用index变量。)

Eθ∧μ

在第一个字符之后循环输入的每个字符。

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

循环执行26次,并生成字符串,该字符串以给定步长从输入的上一个字符开始(0索引)开始执行26步,从而得到字符串。

⌕...λ

查找该字符串中输入的当前字符的位置,如果找不到,则返回-1。

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

除非找不到一个,否则取所有位置的总和,在这种情况下,请使用-1。

≔...θ

保存总和。

⌊Φθ⊕ι

找出最小的非负数之和。

I⌕θ...

用该总和找到第一步的大小并输出。


5

JavaScript,143个字节

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

在线尝试!

感谢Shaggy,使用[...Array(26).keys()]节省了9个字节。



4

果冻28 26 23字节

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

输出为0索引。输入是一个字节串,在任何情况下都可以,但是大写是快得多。

单字母输入必须是特殊情况,并且花费2个字节。._。

在线尝试!

请注意,这是一种蛮力方法。具有四个或更多字母的输入将在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

JavaScript(Node.js) 123121116114 字节

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

在线尝试!

已评论

一世2526s[k++ >> 5]G32×大号大号

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索引。将输入作为字符数组。

感谢仅ASCII格式的12字节的高尔夫创意。


:( close(基于python解决方案)
仅ASCII

100,可能可以打更多的高尔夫球
仅ASCII的


好主意,再增加-1个字节p,=*s,但我不确定带有硬编码罚分的解决方案的理论稳健性...因此,我将常数更改为无穷大(尽管您的值允许再减去2个字节) )。
Kirill L.

仅2个字节,还不错
仅ASCII格式的

3

Python 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,含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

Python 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
基里尔L.

1
另外,那n>99看起来很可疑,这是一个要打破无限循环的任意常数吗?然后,它可能应该像26 * len(w)一样,您将永远不知道输入将是多大。
Kirill L.

1
顺便说一句,您仍然可以list(...)在Py3中摆脱它,也可以摆脱它if165 bytes。另外,请查看此提示主题,我相信您可以使用那里的建议来极大地提高自己的技能!
Kirill L.

1
我不是python专家,但是我认为您可以这样做while p!=c and n>len(w)*26:并摆脱-8个字节的最后if语句。
Spitemaster '18

2
尽管它看起来很糟糕,并且与Python的所有内容背道而驰,但是您可以更改n+=1p+=i在单独的一行上进行更改n+=1;p+=i
nedla2004
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.