aboutsummaryrefslogtreecommitdiff
path: root/challenge-074/jo-37/perl/ch-2.pl
blob: 8cbc7ae0b92ee20b9447559f526b4a08818bc56c (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
#!/usr/bin/perl

use v5.16;
use Test2::V0;
use warnings FATAL => 'all';

use List::Util qw(first);

# The description of the task and the given examples are - to my
# understanding - not consistent.
# 
# "Write a script to print the series of first non-repeating character
# (left -> right) for the given string."
#
# Input: $S = 'ababc'
# Output: 'abb#c'
# Pass 1: "a", the FNR character is 'a'
# Pass 2: "ab", the FNR character is 'b'
#
# The characters chosen in the examples are apparently the "first
# non-repeating character (right -> left). I'd rather call this
# the "last non-repeating" character (LNR).
#
# Maybe this little ambiguity is intentional.  At least it adds a nice
# new aspect.  So this sub provides both variants.

sub nr_char {
	my @arr = split //, shift;
	# mode: fnr or lnr
	my $lnr = shift;
	my (%freq, @head);

	join '', map {
		# While traversing the input string character-wise,
		# count frequencies and collect the (reversed) head.
		$freq{$_}++;

		# Emulate unshift (lnr, reversed) or push (fnr, forward)
		# to augment the head.
		splice @head, $lnr ? 0 : @head, 0, $_;

		# The first singleton character from the (reversed) head
		# is the requested output character.
		(first {$freq{$_} == 1} @head) // '#';
	} @arr;
}

is nr_char('ababc', 1), 'abb#c', 'first example, lnr';
is nr_char('xyzzyx', 1), 'xyzyx#', 'second example, lnr';
is nr_char('ababc'), 'aab#c', 'first example, fnr';
is nr_char('xyzzyx'), 'xxxxx#', 'second example, fnr';

done_testing;