2013-10-04 2 views
-2

У меня есть задание, которое «найти количество строк, который содержит по крайней мере 3 нулей и не более 2 1сок» и мой алфавит содержит только 0 и 1. я пытался писать так:Регулярного выражения в Perl

(if $line =~ /0{3,}/) 

но это дало мне всего лишь 3 "последовательных" нули.

Чем я попытался это:

(if $line =~ /0+0+0+/) 

снова он дал мне последовательные нули.

Какова логика проверки всей строки и найти количество всех нулей в этой строке независимо от того, являются ли они последовательными или нет.

+1

Regex, возможно, не является идеальным инструментом для подсчета совпадений. – TLP

+0

Возможно, но мое задание касается использования регулярного выражения. – jdyg

+0

Чтобы решить вашу проблему, вы должны изучить [Look-around утверждения] (http://perldoc.perl.org/perlre.html#Look-Around-Assertions). – TLP

ответ

2
#match a 0 + anything + 0 + anything + 0, and not (!) 1...1...1 
if (($line =~ /0.*0.*0/) && !($line =~ /1.*1.*1/)) { 
    $count++; 
} 
+0

Но похоже, что вам нужно начинать с нуля. Если я напишу 10000, примет ли он? @FtLie – jdyg

+2

@ user2094920 Регулярное выражение по умолчанию не привязано: оно может совпадать в любом месте строки. Чтобы соответствовать началу строки, используйте '^', например: '/^1 /'. – TLP

0

Этот положительный предпросмотр на основе регулярных выражений должно работать:

/^(?=(?:1*0){3})(?=0*(?:10*){0,2}\z)/ 
+0

Что значит «? =» Означает? – jdyg

+2

Это будет соответствовать только последовательным '0' &' 1' – Toto

+0

@ M42: Спасибо за ваш комментарий, вы были правы. Я исправил регулярное выражение. – anubhava

1

Если она содержит по крайней мере три нуля, она содержит нуль, а затем ноль или более символов, заканчивающуюся нулем, а затем ноль или более символов, за которым следует ноль.

$line =~ /0.*0.*0/s 
    -or- 
$line =~ /^[^0]*0[^0]*0[^0]*0/ # More efficient for strings that don't match. 
    -or- 
$line =~ /^(?:[^0]*0){3}/  # Avoid code repetition 

Если он содержит не более двух единиц, он не содержит по меньшей мере трех.

$line !~ /^(?:[^1]*1){3}/ 

Так,

$line =~ /^(?:[^0]*0){3}/ && $line !~ /^(?:[^1]*1){3}/ 
0

Я бы рассчитывать замену, после того, как все они своего рода часть регулярного выражения, не так ли?

В скалярном контексте s{0}{0}g будет возвращать количество раз, когда была выполнена замена, которая представляет собой число 0 в строке. Таким образом, s{0}{0}g >= 3 && s{1}{1}g <=2 будет условием, которое вы ищете.

Вот небольшая тестовая программа, чтобы проверить это:

#!/usr/bin/perl 

use strict; 
use warnings; 

use Test::More; 

while(<DATA>) 
    { chomp; 
    my($nb, $expected)= split /\s*=>\s*/; 
    # the for topicalizes $nb so we don't have to write it in the condition 
    for ($nb) 
     { my $got= s{0}{0}g >= 3 && s{1}{1}g <=2 ? 'ok' : 'nok'; 
     is($got, $expected, "testing $nb ($expected)"); 
     } 
    } 

done_testing(); 

__DATA__ 
00011 => ok 
01010 => ok 
1000 => ok 
000 => ok 
0000 => ok 
1100000=> ok 
0  => nok 
00  => nok 
1  => nok 
11  => nok 
111 => nok 
10  => nok 
100 => nok 
1100 => nok 
111000 => nok 
010101 => nok 
Смежные вопросы