aboutsummaryrefslogtreecommitdiff
path: root/challenge-128/arne-sommer/raku/minimum-platforms-permutations
blob: e61f55f16016855da1ca22776dcc2a5ebd6f143a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#! /usr/bin/env raku

subset HHMM where $_ ~~ /^(<[012]>)\d\:<[012345]>\d$/ && $0 <= 23;

unit sub MAIN (Str $trains = "11:20 11:50 | 14:30 15:00",
   :l(:$loquacious),
   :v(:$verbose) = $loquacious,
   :p(:$platforms),
); 

class Platform
{
  has Str $.id;
  has Str @.in-use is rw;

  method add-if-vacant (HHMM $from, HHMM $to)
  {
    for @.in-use -> $interval
    {
      my ($start, $end) = $interval.split("-");
      next if $to  lt $start;
      next if $end lt $from;

      return False;
    }

    @.in-use.push: "$from-$to";
    return True;
  }

  method Str
  {
    return ": - Platform: $.id: " ~ @.in-use.sort.join(", ");
  }
}

class Station
{
  has Str      $.name;
  has Platform @.platforms is rw;

  method add-train (HHMM $from, HHMM $to)
  {
    for self.platforms -> $platform
    {
      return True if $platform.add-if-vacant($from, $to);
    }
      
    my $platform = Platform.new(id => (self.number-of-platforms + 1).Str);
    self.platforms.push: $platform;
    return $platform.add-if-vacant($from, $to);
  }

  method number-of-platforms
  {
    return @.platforms.elems;
  }

  method Str
  {
    return ": Station: $.name\n" ~ @.platforms>>.Str.join("\n");
  }
}

my @trains = $trains.split(/\s\|\s+/);

my $number-of-platforms = Inf;

for @trains.permutations -> @trains-p
{
  my $station = Station.new(name => 'Grand Central');

  for @trains-p -> $from-to
  {
    my (HHMM $from, HHMM $to) = $from-to.words;

    die "Train departs ($from) before it arrives ($to)" if $from gt $to;

    say ": Visiting train $from -> $to" if $verbose;

    $station.add-train($from, $to);
  }

  say $station.Str if $loquacious;

  my $platform-count   = $station.number-of-platforms;
  $number-of-platforms = min($number-of-platforms, $platform-count);

  say ": Platforms: $platforms" if $platforms;
}

say $number-of-platforms;