aboutsummaryrefslogtreecommitdiff
path: root/challenge-059/markus-holzer/raku/lib/LinkedList/Simple.pm6
blob: d6aeef33b734b7819087adaa3956167595ab8341 (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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
role LinkedList::Simple::Node
{
	has $.next is rw;

	method LinkedList
	{
		LinkedList::Simple.new( :head( self ) );
	}

	multi method append( $new-value )
	{
		self.append( $new-value but LinkedList::Simple::Node )
	}

	multi method append( LinkedList::Simple::Node $new-node )
	{
		self.next = $new-node
	}

	multi method perl()
	{
		nextsame
				}
}

role LinkedList::Simple does Iterable
{
	has LinkedList::Simple::Node $.head is rw;

	method from( *@nodes )
	{
		self.bless( :@nodes );
	}

	multi submethod BUILD( LinkedList::Simple::Node :$head, :@nodes )
	{
		$!head = my $node = $head // ( @nodes.shift but LinkedList::Simple::Node );
		$node = $node.append( $_ ) for @nodes;
	}

	method sequence()
	{
		$!head, *.next ... ! *.next.defined
	}

	method iterator()
	{
		self.sequence.iterator;
	}

	multi method perl()
	{
		"LinkedList::Simple.from({ self.sequence.map( *.perl ).join(', ') });"
	}

	method roughsort( Code $categorize )
	{
		sub dismantle( &categorize )
		{
			my $end;
			my $start;
			my $head-category = &categorize( self.head );

			gather
			{
				for self.flat -> $node
				{
					if ( $head-category == $node.&categorize )
					{
						take { :$start, :$end } with $end;

						$head-category .= not;
						$start = $node;
					}

					$end = $node;
				}

				take { :$start, :$end };
			}
		}

		sub assemble( $pieces )
		{
			my $first-node;
			my $last-frag;

			for $pieces.rotor( 2 => -1 ) -> ( $left, $right )
			{
				FIRST $first-node = $left<start>;
				LAST $last-frag = $right;

				$left<end>.next = $right<start>;
			}

			with $first-node
			{
				self.head = $first-node;
				$last-frag<end>.next = Any;
			}

			self;
		}

		assemble(
			dismantle( *.$categorize )
			.sort( not *<start>.$categorize ) );

	}
}