Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[crypt.pl] refactor; extract private method

Finding the rod with a certain disk is basically the same
for moving and removing disks, so de-duplicate that functionality.
  • Loading branch information...
commit 00629f15f9bffd032d00f5c2a8dad29fe7a37fc2 1 parent c9e01dd
@masak authored
Showing with 18 additions and 32 deletions.
  1. +18 −32 crypt.pl
View
50 crypt.pl
@@ -98,31 +98,14 @@
has $!achievement = 'locked';
method move($source is copy, $target) {
- my @source_rod;
if $source eq any @disks {
- my $disk = $source;
- for %!state -> ( :key($rod), :value(@disks) ) {
- if $disk eq any(@disks) {
- sub smaller_disks {
- grep { %size_of{$_} < %size_of{$disk} }, @disks;
- }
- die X::Hanoi::CoveredDisk.new(:$disk, :covered_by(smaller_disks))
- unless @disks[*-1] eq $disk;
- @source_rod := @disks;
- $source = $rod;
- last;
- }
- }
- die X::Hanoi::DiskHasBeenRemoved.new(:action<move>, :$disk)
- unless @source_rod;
- }
- else {
- die X::Hanoi::NoSuchRod.new(:rod<source>, :name($source))
- unless %!state.exists($source);
- @source_rod := %!state{$source};
+ $source = self!rod_with_disk($source, 'move');
}
+ die X::Hanoi::NoSuchRod.new(:rod<source>, :name($source))
+ unless %!state.exists($source);
die X::Hanoi::NoSuchRod.new(:rod<target>, :name($target))
unless %!state.exists($target);
+ my @source_rod := %!state{$source};
die X::Hanoi::RodHasNoDisks.new(:name($source))
unless @source_rod;
my @target_rod := %!state{$target};
@@ -151,26 +134,29 @@
}
method remove($disk) {
+ my $source = self!rod_with_disk($disk, 'remove');
my $size = $disk.words[0];
- my $source;
- for %!state -> ( :key($rod), :value(@disks) ) {
+ die X::Hanoi::ForbiddenDiskRemoval.new(:$disk)
+ unless $size eq 'tiny';
+ my @events = Hanoi::DiskRemoved.new(:$size, :$source);
+ self!apply($_) for @events;
+ return @events;
+ }
+
+ # The method will throw X::Hanoi::CoveredDisk if the disk is not topmost,
+ # or X::Hanoi::DiskHasBeenRemoved if the disk isn't found on any rod.
+ method !rod_with_disk($disk, $action) {
+ for %!state -> (:key($rod), :value(@disks)) {
if $disk eq any(@disks) {
sub smaller_disks {
grep { %size_of{$_} < %size_of{$disk} }, @disks;
}
die X::Hanoi::CoveredDisk.new(:$disk, :covered_by(smaller_disks))
unless @disks[*-1] eq $disk;
- $source = $rod;
- last;
+ return $rod;
}
}
- die X::Hanoi::DiskHasBeenRemoved.new(:action<remove>, :$disk)
- unless defined $source;
- die X::Hanoi::ForbiddenDiskRemoval.new(:$disk)
- unless $size eq 'tiny';
- my @events = Hanoi::DiskRemoved.new(:$size, :$source);
- self!apply($_) for @events;
- return @events;
+ die X::Hanoi::DiskHasBeenRemoved.new(:$disk, :$action);
}
# RAKUDO: private multimethods NYI
Please sign in to comment.
Something went wrong with that request. Please try again.