Skip to content

Instantly share code, notes, and snippets.

@Xliff
Last active August 30, 2019 04:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xliff/279d7094df4ad599f67216ffaad2733e to your computer and use it in GitHub Desktop.
Save Xliff/279d7094df4ad599f67216ffaad2733e to your computer and use it in GitHub Desktop.
This is why you should never do all nighters while sleep deprived and drinking your juice in South Central
enum TakeEnum <TAKE_NONE TAKE_ONE TAKE_TWO>;

my @a = (
    "a", TAKE_NONE,
    "b", TAKE_ONE, 1,
    "c", TAKE_TWO, 'd', 22/7
);
sub separate(@ar) {
    my ($state, $count, $pull) = ('Arg');
    
    do gather for @ar -> $e {
        $state = 'Slurp' if $pull;
        given $state {
            when 'Arg'       { take $e; $state = 'Param';               } 
            when 'Param'     { take ($state = $e); $count = 2; proceed; }
            when TAKE_NONE   { $pull = 0; $state = 'Slurp'; proceed }
            when TAKE_ONE    { $pull = 1; }
            when TAKE_TWO    { $pull = 2; }
            
            when 'Slurp'     { 
              if $pull { take $e; $pull--; $count--; $state = 'Arg' unless $pull; } 
              else     { take 0 for ^$count; $count = $pull = 0; $state = 'Arg'; }
            }
        }
    }
}
@a.&separate.say  # Should be: a TAKE_NONE 0 0 b TAKE_ONE 1 0 c TAKE_TWO d 3.142857
@Xliff
Copy link
Author

Xliff commented Aug 29, 2019

This works, but isn't there a better way?

enum TakeEnum <TAKE_NONE TAKE_ONE TAKE_TWO TAKE_THREE>;

my @a = (
    "a", TAKE_NONE,
    "b", TAKE_ONE, 1,
    "c", TAKE_TWO, 'd', 22/7,
    "E", TAKE_THREE, 'a', 'b', '»'
);

sub separate(@ar) {
    my ($state, $count, $pull) = ('Arg');
    
    do gather for @ar -> $e {
        $state = 'Slurp' if $pull;
        given $state {
            when 'Arg'       { take $e; $state = 'Param';               } 
            when 'Param'     { take ($state = $e); $count = 3; proceed; }
            when TAKE_NONE   { $pull = 0; $state = 'Slurp'; proceed }
            when TAKE_ONE    { $pull = 1; }
            when TAKE_TWO    { $pull = 2; }
            when TAKE_THREE  { $pull = 3; }
            
            when 'Slurp'     { 
              if $pull { take $e; $pull--; $count--; $state = 'Arg' unless $pull; } 
              unless $pull { take 0 for ^$count; $count = $pull = 0; $state = 'Arg'; }
            }
        }
    }
}

@a.&separate.say  # Should be: a TAKE_NONE 0 0 b TAKE_ONE 1 0 c TAKE_TWO d 3.142857

@Xliff
Copy link
Author

Xliff commented Aug 30, 2019

Here's a leaner version...

my @a = (
    "a", TAKE_NONE,
    "b", TAKE_ONE, 1,
    "c", TAKE_TWO, 'd', 22/7,
    "E", TAKE_THREE, 'a', 'b', '»'
);

sub separate(@ar) {
    my ($state, $count, $pull) = ('Arg');
    
    my $max-count = TakeEnum.enums.values.max;
    
    do gather for @ar -> $e {
        given $state {
            when 'Arg'       { take $e; $state = 'Param';  } 
            when 'Param'     { take ($state = $e); 
                               $count = $max-count;
                               $pull = $e.Int;
                               $state = 'Slurp';
                               proceed unless $pull        }
            
            when 'Slurp'     { 
              if $pull { take $e; $pull--; $count--;  } 
              unless $pull { take 0 for ^$count; $count = $pull = 0; $state = 'Arg'; }
            }
        }
    }
}

@a.&separate.say  # Output: (a TAKE_NONE 0 0 0 b TAKE_ONE 1 0 0 c TAKE_TWO d 3.142857 0 E TAKE_THREE a b »)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment