#!/usr/bin/perl use v5.14; use strict; use utf8; binmode STDOUT, ':utf8'; sub wghtrandsel { # selects in a weighted randomized manner my $multices = ref $_[-1] eq 'HASH' ? pop : {}; my @simple = split "", shift//""; while ( my ($num, $mult) = each $multices ) { my @values = ref $mult eq 'ARRAY' ? @$mult : $mult; push @simple, ($_) x $num for @values; } return sub { my $c = $simple[ int rand @simple ]; return (ref $c ? $c->() : $c) // ""; } } sub chained { my @args = @_; return sub { join "", map { ref $_ ? $_->() : $_ } @args }; } my $weak_vowel = wghtrandsel("aaaeeeiiooouu"); my $strong_vowel = wghtrandsel("áóéàòèâôêãõẽíúîû"); # PM bug? ^^^^^^^ => e + ~ my $weak_diphthong = wghtrandsel({ 3 => chained( wghtrandsel("ae"), wghtrandsel({ 5 => "i", 1 => "u" }) ), 2 => chained( "o", wghtrandsel({ 5 => "u", 1 => "i" }) ), 1 => [ "uy", "iw" ], }); my $strong_diphthong = wghtrandsel({ 3 => chained( wghtrandsel("áé"), wghtrandsel({ 5 => "i", 2 => "u" }) ), 1 => chained( "ó", wghtrandsel({ 5 => "u", 3 => "i" }) ), 1 => [ "úy", "úa", "íw", "ía" ], }); my $nonplosive = wghtrandsel("cfjlmnrsvxz", { 1 => ['hn','hr'] }); my $plosive = wghtrandsel("bdgkpqt"); my $initial_consonant = wghtrandsel({ 5 => $nonplosive, 2 => wghtrandsel({ 1 => [qw[ch fh jh sh vh zh h]] }), 3 => chained( $plosive, wghtrandsel({ 6 => undef, 1 => ["w", "y", "l", "r"] }), ), 1 => ["y","w"] }); my $stressed_syllable = chained( $initial_consonant, wghtrandsel({ 2 => $strong_vowel, 1 => $strong_diphthong }), wghtrandsel({ 3 => $nonplosive, 5 => undef }), ); my $stressed_initial_syllable = wghtrandsel({ 3 => $stressed_syllable, 1 => chained( wghtrandsel({ 3 => $strong_vowel, 2 => $strong_diphthong }), wghtrandsel({ 4 => undef, 1 => $nonplosive }) ), }); my $unstressed_syllable = chained( $initial_consonant, wghtrandsel({ 3 => chained( $weak_vowel, wghtrandsel({ 8 => undef, 1 => $nonplosive }) ), 2 => $weak_diphthong, }), ); my $word = wghtrandsel({ 1 => [ $stressed_initial_syllable, $unstressed_syllable ], 4 => chained( wghtrandsel({ 5 => $stressed_initial_syllable, 2 => chained($unstressed_syllable, $stressed_syllable), }), $unstressed_syllable ), }); say $word->() for 1 .. 1000; 1;