2012-06-14 5 views
0

다음 입력이 주어진 경우Perl : 문자열 내의 숫자 비교

A | 11 162 60 90 - 141 184

B | 231 322 - 306 305 285 350

A의 경우, (11,162) 또는 (60,90)을 포함하여 141이 거짓인지 확인하고 싶습니다. 예인 경우 "In A, 141 lies between (11,162)"를 인쇄하십시오.

그런 다음 184 개가 (11,162) 개 또는 (60,90 개) 사이에 있는지 확인하고 싶습니다. 아니기 때문에 인쇄 할 필요가 없습니다.

마찬가지로 B의 경우 (231, 322) 사이에있는 숫자를 인쇄해야합니다.

다음 Perl 코드를 작성했지만 올바른 출력을 얻지 못했습니다.

#!/usr/bin/perl -w 
open LIST, "input.txt"; 
while($line=<LIST>) 
{ 
@elem=split (/\|/,$line); 
@nextone=split("--",$elem[1]); 
@nextoneone = split(" ",$nextone[0]); 
@nexttwo=split(" ",$nextone[1]); 

if ($nexttwo[0] > $nextoneone[0] && $nexttwo[0] < $nextoneone[1]) 
{ 
print"$elem[0]\t $nexttwo[0]\t $nextoneone[0]\t $nextoneone[1]\n"; 
} 
elsif ($nexttwo[0] > $nextoneone[2] && $nexttwo[0] < $nextoneone[3]) 
{ 
print"$elem[0]\t $nexttwo[0]\t $nextoneone[2]\t $nextoneone[3]\n"; 
} 
elsif ($nexttwo[1] > $nextoneone[0] && $nexttwo[1] < $nextoneone[1]) 
{ 
print"$elem[0]\t $nexttwo[1]\t $nextoneone[0] \t$nextoneone[1]\n"; 
} 
elsif ($nexttwo[1] > $nextoneone[2] && $nexttwo[1] < $nextoneone[3]) 
{ 
print"$elem[0]\t $nexttwo[1]\t $nextoneone[2] \t$nextoneone[3]\n"; 
} 
} 
    close (LIST); 
    exit; 

각 행에 몇 개의 요소가 있는지 알 수 없습니다. 따라서 비교를 위해 루프를 구현하는 방법을 모르겠습니다. 코드를 개선하는 방법에 대한 지침은 만족 스러울 것입니다.

도움 주셔서 감사합니다.

답변

1

첫째, 당신의 스크립트에 대한 몇 가지를 변경합니다. 1) 엄격한 사용 - 어떤 오타도 잡을 수 있음을 의미합니다.

2) 변수를 좀 더 의미있는 이름으로 바꿉니다. 내가 본 것을 바탕으로 의미가 바뀌었지만 스크립트가하는 일을 모릅니다. 이

를 작동하지 않는 이유는 당신이 그것을 개발하는 동안 당신은 더 나은 사람

3

) 출력 일부 디버그가있을 수 있습니다, 그래서 당신이 무엇을하고 있는지 볼 수 있습니다, 당신은 두 개의 루프가 필요합니다 - 루프를 통해 '-'의 왼쪽에있는 문자열의 부분에있는 값과 오른쪽에있는 조건에 대해 하나의 루프를 반복합니다. 외부 루프의 값을 반복 할 때마다 내부 루프의 모든 조건을 반복해야합니다.

use strict; 
    #!/usr/bin/perl -w 
    open LIST, "input.txt"; 
    my $line; 
    while($line=<LIST>) { 
     my ($label, $content) =split (/\|/,$line); 
     my ($conditionstring, $valuestring) =split("--",$content); 
     my (@conditions) = split(" ",$conditionstring); 
     my (@values) =split(" ",$valuestring); 
     foreach my $this_val (@values) { 
       my $matched_one_condition = 0; 
       for (my $f=0; $f< scalar(@conditions);$f+=2) { 


         print "Comparing $this_val to $conditions[$f] and to   $conditions[$f+1]\n"; 

         if (($this_val > $conditions[$f]) && ($this_val < $conditions[$f+1])) { 
           $matched_one_condition= 1; 

         } 
       } 
       if ($matched_one_condition) { 
         print "$this_val\n"; 

       } 
     } 
} 

주 - 내가 거기에

+0

안녕하세요. 그것은 작동합니다. – zock

0

당신이 그들의 수를 모르는 경우 값을 통해 루프를 사용

#!/usr/bin/perl 
use warnings; 
use strict; 
use feature 'say'; 

while (<DATA>) { 
    my ($header, $rangeS, $pointS) = /(.*)\|(.*) -- (.*)/; 
    my @ranges = $rangeS =~ /([^ ]+ [^ ]+)/g; 
    my @points = split//, $pointS; 

    for my $point (@points) { 
     for my $range (@ranges) { 
      my ($from, $to) = split//, $range; 
      if ($from <= $point and $point <= $to) { 
       say "In $header, $point lies between ($from,$to)"; 
       last; # Comment this line to get all the ranges for each point. 
      } 
     } 
    } 
} 

__DATA__ 
A| 11 162 60 90 -- 141 184 
B| 231 322 -- 306 305 285 350 
C| 10 20 30 40 -- 1 2 3 4 5 6 7 8 9 
D| 10 20 10 40 -- 1 10 20 40 10 
0

에서 디버그 라인을 떠 났어요 내가 당신의 문제에 강타했다. 잘하면 당신은 그것에 가치를 발견 할 수 있습니다. 나는 라인 B의 경우를 처리하기 위해 범위를 정렬하는 자유를 취했다. 306, 305.

#!/bin/env perl 
use strict; 
use warnings; 

while (<DATA>) { 
    my @line = /\w+|\d+/g; 
    my($h, $ranges, $tests) = (
     $line[0], [ [ sort @line[1,2] ], [ sort @line[3,4] ] ], [ @line[5,6] ] 
    ); 
    map { 
     my $test = $_; 
     map { 
      print "In $h, $test lies between (", join(', ', @$_), ")\n" 
       if grep { /^$test$/ } ($_->[0] .. $_->[1]) 
     } (@$ranges) 
    } @$tests 
} 

__DATA__ 
A| 11 162 60 90 -- 141 184 
B| 231 322 -- 306 305 285 350