我提出了以下正则表达式,作为检查由连续序列中的一组数字按升序或降序组成的数据的方法。
明显的约束:字符串长度在2到10位之间,因为一个数字不是序列,十几个数字必须重复。其他代码将确保输入只包含数字。 (例如 /\A\d{2,}\z/
)
示例:
'012'
,'9876'
和'56'
应匹配'7'
,'013'
,'6554'
和'09'
不应该我认为这可以胜任:
/(?:\A(?:0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)|\d(?!\d)){2,}\z)|
(?:\A(?:1(?=0)|2(?=1)|3(?=2)|4(?=3)|5(?=4)|6(?=5)|7(?=6)|8(?=7)|9(?=8)|\d(?!\d)){2,}\z)/x
问题在于:您能否在Ruby兼容的正则表达式中看到更简洁或更美妙的表达方式?
显然,一些嵌套循环将是解决同一问题的非正则表达式。
if num.length > 1
[Proc.new { |n| n + 1 }, Proc.new { |n| n - 1 }].each do |p|
is_sequential = true
(0..num.length - 2).each do |i|
if p.call(num[i].ord) != num[i + 1].ord
is_sequential = false
break
end
end
return 'Number is sequential' if is_sequential
end
end
注意使它更紧凑或更漂亮?
答案 0 :(得分:3)
def isseq( s )
1 < s.length && !!( '0123456789'[s] || '9876543210'[s] )
end
[ '012', '9876', '56', '7', '013', '6554', '09' ].each do |test|
puts "#{test} #{isseq(test)}"
end
输出:
012 true
9876 true
56 true
7 false
013 false
6554 false
09 false
对于super_string的想法以及使用str [s]的Tin Man来说,信用是真的。
答案 1 :(得分:2)
super_string = "0123456789"
'012'.scan(/\d{2,10}/).
map{|x| super_string.include?(x) || super_string.reverse.include?(x) }.
uniq == [true]
#=> true
'013'.scan(/\d{2,10}/).map{|x| super_string.include?(x) || super_string.reverse.include?(x) }.uniq == [true]
#=> false
注意:如果给定的字符串具有n&gt;的(10n + 1)个数字,则返回true。如果除了last之外的所有数字都按顺序排列为0如果不是必需的输出,可以修改它以返回false。
答案 2 :(得分:2)
对于给定的初始数字和字符串长度,只有两个可能的有效字符串。只需生成它们并进行比较。
def sequential_num(num)
return false if num =~ /\D/ or num.length <= 1
initial = num[0]
range = (num.length - 1)
final = (initial.ord + range).chr
return true if final <= '9' and num == (initial..final).to_a.join
final = (initial.ord - range).chr
return true if final >= '0' and num == (final..initial).to_a.reverse.join
return false
end
%w/ 012 9876 56 7 013 6554 09 /.each do |num|
puts '%-4s %s' % [ num, sequential_num(num) ? 'match' : 'no match' ]
end
<强>输出强>
012 match
9876 match
56 match
7 no match
013 no match
6554 no match
09 no match
答案 3 :(得分:2)
编辑:我误解了这个问题。最初我有:
10美元说你要打你的额头。s = str.split('')
sorted = s.sort
sorted == s || sorted == s.reverse
我将解决方案改为:
s = "0123456789"
s.include?(str) || s.reverse.include?(str)
然后看到@Matt已经给出了这个解决方案。
我在此撤回我提出的赌注。
答案 4 :(得分:2)
Dan,有时候会想到在进行模式匹配时应该放置什么。这里有趣的是'0123456789 9876543210'是一个包含每个可能正确答案的字符串。一旦我们将输入验证为所有数字,长度> 1,就可以使用模式匹配来查看数据是否出现在解决方案的范围内。我说Perl很好,所以我会坚持下去。这是一般性测试:
因此$nstring
已经过验证数字,长度> 1。
print "$nstring matches!\n" if '0123456789 9876543210' =~ /$nstring/;
或者是一个简单的程序审核合适的字符串然后测试:
while (<STDIN>)
{
chomp;
next if not /^[0-9]{2,}$/;
$nstring=$_;
$matches='0123456789 9876543210' =~ /$nstring/?"matches":"does not match";
print "$nstring $matches!\n";
}
答案 5 :(得分:2)
以下是elixir中非正则表达式功能解决方案的尝试:
#!/usr/bin/env elixir
defmodule Seq do
def is_seq(list) when match([x, y | t], list), do: is_desc(list) || is_asc(list)
def is_seq(_), do: false
def is_desc([first, second | tail]), do: second == first - 1 && is_desc [second | tail]
def is_desc(_), do: true
def is_asc([first, second | tail]), do: second == first + 1 && is_asc [second | tail]
def is_asc(_), do: true
def test() do
['012', '9876', '56', '7', '013', '6554', '09', '012345678', '01234678'] |> Enum.map &is_seq/1
end
end
Seq.test |> IO.inspect
答案 6 :(得分:1)
我认为正则表达式对于这项工作并不是一个好主意。我们的问题可以简化为“每个数字之间差异的绝对值应该只有一个”,简单地说:
irb(main):052:0> s
=> "2345678"
irb(main):053:0> pairs = s.chars.zip(s[1..10].chars).select {|i| i[0] and i[1]}
=> [["2", "3"], ["3", "4"], ["4", "5"], ["5", "6"], ["6", "7"], ["7", "8"]]
irb(main):054:0> pairs.all? {|i| (i[0].to_i - i[1].to_i).abs == 1}
=> true
其他要求可以通过"23647".chars.uniq!
等简单检查来实现。
编辑:无需支票,如果套装有重复的数字,我们的主要要求也会失败。