fork(1) download
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5.  
  6. # The loop has been added for easy verification of multiple inputs
  7. until (eof) {
  8. # Read the line with the lengths and convert it into an array
  9. my $line = <>;
  10. my @lengths = split /\s+/, $line;
  11.  
  12. # Create a regex pattern from the lengths. It begins with any number of
  13. # non 'x' or '_' characters
  14. my $re = '[x_]*';
  15. for (@lengths) {
  16. # Example: if a length was 3, then the pattern will be appended with
  17. # ([#_]{3})[x_]+ which matches a 3 character combination of '#' and '_'
  18. # and then 'x's (spaces) or '_'s (unkown characters) after that
  19. $re .= "([#_]{$_})[x_]+";
  20. }
  21.  
  22. # Replace the last + with * since we don't need to have non '#' characters
  23. # at the end
  24. $re =~ s/\+$/*/;
  25.  
  26. # Read the pattern and remove the new line
  27. my $pat = <>;
  28. chomp $pat;
  29.  
  30. # At every index of this array is a concatenation of all patterns that matched
  31. # the length at that index
  32. my @matched_parts;
  33.  
  34. {
  35. # We need to be less strict to use $$_ (i.e. $1, $2, $3 etc) which are
  36. # the groups captured during the regex match
  37. no strict 'refs';
  38.  
  39. # The complete pattern is matched with the regex generated earlier -
  40. # hence the ^..$.
  41. #
  42. # The code within (?{...}) is executed if the regex matched
  43. # successfully. Inside the code, we append the matched sub-patterns ($1
  44. # for the first length, $2 for the second etc) for every length to the
  45. # right element inside @matched_parts. $$_ will result in $1, $2, $3
  46. # etc for $_ = 1, 2, 3 etc.
  47. #
  48. # The (?!) at the end - i.e. a negative look ahead with no characters -
  49. # ensures that after the generated regex matches successfully, the
  50. # complete pattern match still fails, thus forcing the regex engine to
  51. # backtrack. This way, we iterate over all possible matches of the 1st
  52. # part and execute the code for them.
  53. $pat =~ /
  54. ^$re$ # match the complete pattern with the constructed regex
  55. (?{ # code to execute on successful match. the comma is only added
  56. # for clarity
  57. $matched_parts[$_-1].=",$$_" for 1..@lengths
  58. })
  59. (?!) # fail the match after the code is executed
  60. /x;
  61.  
  62. # Uncomment the following to see the value of @matched_parts
  63. #use Data::Dumper;
  64. #$Data::Dumper::Terse = 1;
  65. #$Data::Dumper::Indent = 3;
  66. #print "Matched Parts: " . Dumper(\@matched_parts);
  67. }
  68.  
  69. if (@matched_parts) {
  70. # We have a match, so the lengths can be fitted inside the pattern.
  71. # Now to see if there are any unambiguous matches
  72. for (0..$#lengths) {
  73. # For every length, check if @matched_parts does not have any
  74. # '_' characters in the corresponding index. This means that only
  75. # '#' characters have matched every time implying that there are
  76. # no ambiguities. Print such indices.
  77. print "$_ " if $matched_parts[$_] !~ /_/;
  78. }
  79. print "\n";
  80. } else {
  81. print "ERROR\n";
  82. }
  83. }
  84.  
  85.  
Success #stdin #stdout 0s 6132KB
stdin
3 6 1 4 6
###x######x#x####x######
1 2 1
#____xx___##__x_#
1 2 1
____#___x
1 2 1
#_#x_#
1 2 1
#____#
1 1 1 1
__#_______#____
4 4
______x####________
4 4
__x####________
3
__x__
5 1 3
x#####x____#____
stdout
0 1 2 3 4 
0 1 2 

ERROR
0 2 


0 
ERROR
0