使用ruby生成表示数字的字母?
我想生成一系列字母,即“a”、“DE”、“GJE”等,它们对应于一个数字。前26个非常简单,因此3个返回“C”,26个返回“Z”,27个返回“AA”,28个返回“AB”,依此类推 我不太清楚的是如何做到这一点,这样它就可以处理传入的任何数字。所以,如果我通过4123,我应该会得到一些3个字母的组合,因为(26*26*26)最多允许+17000个组合使用ruby生成表示数字的字母?,ruby,math,numerical,Ruby,Math,Numerical,我想生成一系列字母,即“a”、“DE”、“GJE”等,它们对应于一个数字。前26个非常简单,因此3个返回“C”,26个返回“Z”,27个返回“AA”,28个返回“AB”,依此类推 我不太清楚的是如何做到这一点,这样它就可以处理传入的任何数字。所以,如果我通过4123,我应该会得到一些3个字母的组合,因为(26*26*26)最多允许+17000个组合 有什么建议吗?使用找到的基本转换方法。我还更改了它,因为我们在这个编号系统中没有“0”。最终案例已得到解决 class Numeric Alph
有什么建议吗?使用找到的基本转换方法。我还更改了它,因为我们在这个编号系统中没有“0”。最终案例已得到解决
class Numeric
Alph = ("a".."z").to_a
def alph
s, q = "", self
(q, r = (q - 1).divmod(26)); s.prepend(Alph[r]) until q.zero?
s
end
end
3.alph
# => "c"
26.alph
# => "z"
27.alph
# => "aa"
4123.alph
# => "fbo"
def baseAZ(num)
# temp variable for converting base
temp = num
# the base 26 (az) number
az = ''
while temp > 0
# get the remainder and convert to a letter
num26 = temp % 26
temp /= 26
# offset for lack of "0"
temp -= 1 if num26 == 0
az = (num26).to_s(26).tr('0-9a-p', 'ZA-Y') + az
end
return az
end
irb I/O:
>> baseAZ(1)
=> "A"
>> baseAZ(26^2 + 1)
=> "Y"
>> baseAZ(26*26 + 1)
=> "ZA"
>> baseAZ(26*26*26 + 1)
=> "YZA"
>> baseAZ(26*26*26 + 26*26 + 1)
=> "ZZA"
字符串确实有一个
succ
方法,因此它们可以在一定范围内使用。“Z”的后继者恰好是“AA”,因此这是可行的:
h = {}
('A'..'ZZZ').each_with_index{|w, i| h[i+1] = w }
p h[27] #=> "AA"
根据sawa的回答,我想要一种独立工作的方法,尽管是递归的,以实现期望的结果:
def num_to_col(num)
raise("invalid value #{num} for num") unless num > 0
result, remainder = num.divmod(26)
if remainder == 0
result -= 1
remainder = 26
end
final_letter = ('a'..'z').to_a[remainder-1]
result > 0 ? previous_letters = num_to_col(result) : previous_letters = ''
"#{previous_letters}#{final_letter}".upcase
end
对@sawa的调整是Ruby 2.0的原始答案,因为我无法让他按原样工作:
class Numeric
Alpha26 = ("a".."z").to_a
def to_s26
return "" if self < 1
s, q = "", self
loop do
q, r = (q - 1).divmod(26)
s.prepend(Alpha26[r])
break if q.zero?
end
s
end
end
用法:
1234567890.to_s26
# => "cywoqvj"
"cywoqvj".to_i26
# => 1234567890
1234567890.to_s26.to_i26
# => 1234567890
"".to_i26
# => 0
0.to_s26
# => ""
我喜欢这个答案: 下面是一个简短的基于性能递归的解决方案
类数值
#“z”被放置在数组的开头,因为26%26是0而不是26
Alph=['z']+(“a“.“y”)。到a
def to_alph
#如果self为0或负值,则返回一个空字符串。
#这还用于结束to_alph调用的递归链
#因此,不要将此替换为引发错误或返回任何其他内容
如果self<1,则返回“”
#(否则)返回两个串联字符串:
#右侧是用于自我模块26的字母
#左侧由以下部分组成:
# 1. 减1,因为这不是基于零的编号系统。
#因此,整数(26,52…)应返回一位数字“z”
#而不是两位数字“aa”或“ba”。
# 2. 除以26,然后打电话给阿尔普。
#对于最后一个字符串的每个数字,它都会递归重复,
#再加一次,它将返回“”以结束递归链。
返回((self-1)/26)。到_alph+alph[self%26]
结束
结束
通过从字母表的序号中减去96,可以得到字符在字母表中的数字位置,如下所示:
"a".ord - 96
=> 1
"z".ord - 96
=> 26
(1 + 96).chr
=> "a"
(26 + 96).chr
=> "z"
您还可以通过添加96,通过其数字位置获取字母字符,如下所示:
"a".ord - 96
=> 1
"z".ord - 96
=> 26
(1 + 96).chr
=> "a"
(26 + 96).chr
=> "z"
这基本上是一个基数为26的数字(但基数中没有数字)@SergioTulentsev-事实证明,这个问题更复杂。我认为导致麻烦的关键特征是
A
在某些情况下意味着“0”(作为“一”位),但A
在其他情况下意味着“1”(作为“十/二十六”位。有趣的是,微软的某个人必须解决这个问题;)我遗漏了一些东西。为什么“A”是特别的?A=1*1=1,AA=1*26+1*1=27。@glennmcdonald“A”并不特别。“A”始终对应于“1”。特别的是跳过了“0”。想象一下十进制,向上计数,跳过“0”:1,2,…,8,9,11,12,…,18,19,21,22,…,98,99,111,112。。。现在,如果你用七进制(以27为基数)而不是十进制,你就得到了序列。哦,对了。在Base26中可能更容易实现,因为它的值为0。不清楚零的东西是需求还是想象解决方案的产物。我相信这是目前为止唯一正确的解决方案,尽管我不确定到底发生了什么……太棒了。我还从中获得了新的见解。计算总组合的方法如下!(26^(n-1))。我不是数学家,所以这可能是完全虚构的,但这会给你(26^3)+(26^2)+(26^1)表示三个字母,和(26^2)+(26^1)表示两个字母,等等。在rails应用程序中使用这个的最佳方式是什么?要在lib目录中包含该类并需要它?@JeremyRichards将其放在config/initializers/numeric.rb
fileInsightful中,注意这个数字系统“缺少零”,尽管事后看来很明显。我发现OP希望转换为,通过该关键字搜索,似乎没有基于音译的转换算法。我认为一个简单的基于音译的算法是不可能的,因为在无零系统中总会有一个单位数符号,必须映射到零系统中的一个两位数符号。使用这种方法,你不能当场随机计算某个数字的字符串,但是你必须通过所有的数字来达到目标数字。出于性能原因,Sawa的答案要好得多,但是如果你将此响应作为一种快速而肮脏的方法,那么下面一行就可以做到:x=27;('A'..'ZZZ')。如果(i+1)=x;i+1},则减少(0){i,l | break(l)}实际上这比@Sawa快(根据结果是17倍),前提是哈希被重复使用。这样做的代价是使用更多的内存。这个答案是为一个固定的范围预先生成散列,并且只在需要时引用它。我的答案是当场生成任意序列的。他们无法比较,这是一个很好的发现。我已经更新了我的答案,因此小于1的任何内容都将返回空字符串。请注意,字符串#to_i26方法会修改它在下套管时调用的字符串。要改变这一点,请改变downcase
到string=downcase
和char=self[-i]
到char=string[-i]
这是一个很好的解决方案。根据这个问题,这不太管用。例如,27应该返回“AA”,这个返回“BB”。这个答案不起作用。问题是27应该返回“AA”,这个方法返回“BB”对不起-这个答案适用于我的情况,我不关心生成的确切字母,但我同意这是错误的。我最终使用了这个,因为我需要一个零
(1 + 96).chr
=> "a"
(26 + 96).chr
=> "z"