From 53cd8b116eca829c09801cef14a07d45f36f9e17 Mon Sep 17 00:00:00 2001
From: "Jan \"Yenya\" Kasprzak" <kas@fi.muni.cz>
Date: Thu, 16 Dec 2021 09:32:12 +0100
Subject: [PATCH] 32.pl: cleanup

---
 32.pl | 87 +++++++++++++++++++++++------------------------------------
 1 file changed, 33 insertions(+), 54 deletions(-)

diff --git a/32.pl b/32.pl
index 035abc7..390c25d 100755
--- a/32.pl
+++ b/32.pl
@@ -2,81 +2,60 @@
 
 use v5.16;
 
-chomp(my $packet = <>);
-$packet =~ s/./sprintf("%04b", hex $&)/ge if $packet =~ /[2-9A-F]/;
+chomp(my $data = <>);
+# Accept also a binary string instead of hexadecimal one:
+$data =~ s/./sprintf("%04b", hex $&)/ge if $data =~ /[2-9A-F]/;
 
-sub get_b (\$$) {
-	my ($ppack, $bits) = @_;
+sub chop_bits {
+	my ($bits) = @_;
 	my $rv;
-	$$ppack =~ s/.{$bits}/$rv=eval"0b$&";''/e;
-	# say "get_b $bits=$rv";
+	$data =~ s/.{$bits}/$rv = eval "0b$&"; ''/e;
+	# say "chop_bits($bits) = $rv";
 	return $rv;
 }
 
 my $ver_sum;
 my $result;
-sub parse {
-	my $pp = shift;
 
-	my $l = length $pp;
-	my $ver = get_b($pp, 3);
-	$ver_sum += $ver;
-	my $typ = get_b($pp, 3);
+sub parse {
+	$ver_sum += chop_bits(3);
+	my $type = chop_bits(3);
 
-	if ($typ == 4) {
+	if ($type == 4) {
 		my $num = 0;
-		while (get_b($pp, 1)) {
+		my $more;
+		do {
+			$more = chop_bits(1);
 			$num *= 16;
-			$num += get_b($pp, 4);
-		}
-		$num *= 16;
-		$num += get_b($pp, 4);
+			$num += chop_bits(4);
+		} while ($more);
 		$result .= "$num,";
 	} else {
-		$result .= "op($typ,";
-		my $li = get_b($pp, 1);
-		if ($li) {
-			my $subp = get_b($pp, 11);
-			for (1 .. $subp) {
-				my $l1 = parse($pp);
-				$pp =~ s/.{$l1}//;
-			}
+		$result .= "op$type(";
+		if (chop_bits(1)) {
+			my $subparts = chop_bits(11);
+			parse() for 1 .. $subparts;
 		} else {
-			my $subl = get_b($pp, 15);
-			my $s = substr($pp, 0, $subl);
-			$pp =~ s/.{$subl}//;
-			while ($subl) {
-				my $l1 = parse($s);
-				$s =~ s/.{$l1}//;
-				$subl -= $l1;
-			}
+			my $sublen = chop_bits(15);
+			my $len = length $data;
+			parse() while $len - length($data) < $sublen;
 		}
 		$result .= "),";
 	}
-	return $l - length($pp);
 }
 
 use List::Util qw(sum product min max);
 
-sub op {
-	my ($id, @rest) = @_;
-	if ($id == 0) {
-		return sum @rest;
-	} elsif ($id == 1) {
-		return product @rest;
-	} elsif ($id == 2) {
-		return min @rest;
-	} elsif ($id == 3) {
-		return max @rest;
-	} elsif ($id == 5) {
-		return $rest[0] > $rest[1] ? 1 : 0;
-	} elsif ($id == 6) {
-		return $rest[0] < $rest[1] ? 1 : 0;
-	} elsif ($id == 7) {
-		return $rest[0] == $rest[1] ? 1 : 0;
-	} 
-}
+sub op0 { sum @_; }
+sub op1 { product @_; }
+sub op2 { min @_; }
+sub op3 { max @_; }
+sub op5 { $_[0] >  $_[1] ? 1 : 0 }
+sub op6 { $_[0] <  $_[1] ? 1 : 0 }
+sub op7 { $_[0] == $_[1] ? 1 : 0 }
+
+parse();
 
-parse($packet);
+say "versions = $ver_sum";
 say $result, ' = ', eval $result;
 
-- 
2.43.5