aboutsummaryrefslogtreecommitdiff
path: root/challenge-162
diff options
context:
space:
mode:
authorMohammad S Anwar <mohammad.anwar@yahoo.com>2022-04-28 02:55:39 +0100
committerMohammad S Anwar <mohammad.anwar@yahoo.com>2022-04-28 02:55:39 +0100
commit7bf95509a49cadc9b91fdd092b0642f8bae210dc (patch)
tree9a8fc753477f03e0de48b1d7ddd64a1b871594eb /challenge-162
parent526a273f4ff4be2fea95c472e97d9b821524835f (diff)
downloadperlweeklychallenge-club-7bf95509a49cadc9b91fdd092b0642f8bae210dc.tar.gz
perlweeklychallenge-club-7bf95509a49cadc9b91fdd092b0642f8bae210dc.tar.bz2
perlweeklychallenge-club-7bf95509a49cadc9b91fdd092b0642f8bae210dc.zip
- Added solutions by Ulrich Rieke.
Diffstat (limited to 'challenge-162')
-rw-r--r--challenge-162/ulrich-rieke/cpp/ch-1.cpp42
-rw-r--r--challenge-162/ulrich-rieke/haskell/ch-1.hs29
-rw-r--r--challenge-162/ulrich-rieke/haskell/ch-2.hs148
-rw-r--r--challenge-162/ulrich-rieke/perl/ch-1.pl30
-rw-r--r--challenge-162/ulrich-rieke/raku/ch-1.raku23
-rw-r--r--challenge-162/ulrich-rieke/raku/ch-2.raku199
6 files changed, 471 insertions, 0 deletions
diff --git a/challenge-162/ulrich-rieke/cpp/ch-1.cpp b/challenge-162/ulrich-rieke/cpp/ch-1.cpp
new file mode 100644
index 0000000000..c4e833f850
--- /dev/null
+++ b/challenge-162/ulrich-rieke/cpp/ch-1.cpp
@@ -0,0 +1,42 @@
+#include <string>
+#include <vector>
+#include <iostream>
+
+std::vector<int> convert( std::string & numberstring ) {
+ std::vector<int> numbers ;
+ for ( int i = 0 ; i < numberstring.size( ) ; i++ ) {
+ if ( numberstring.substr( i , 1 ) != "-" ) {
+ numbers.push_back( std::stoi( numberstring.substr( i, 1) ) ) ;
+ }
+ }
+ return numbers ;
+}
+
+int main( ) {
+ std::cout << "Please enter an ISBN string with only 12 digits!\n" ;
+ std::string isbn ;
+ std::cin >> isbn ;
+ std::string converted ( isbn ) ;
+ std::vector<int> numbers { convert( converted ) } ;
+ while ( numbers.size( ) != 12 ) {
+ std::cout << "Enter an ISBN with only 12 digits, for exercise purposes!\n" ;
+ std::cin >> isbn ;
+ converted = isbn ;
+ numbers = convert( converted ) ;
+ }
+ std::cout << std::endl ;
+ std::vector<int> multipliers ;
+ for ( int i = 0 ; i < 6 ; i++ ) {
+ multipliers.push_back( 1 ) ;
+ multipliers.push_back( 3 ) ;
+ }
+ int sum = 0 ;
+ for ( int i = 0 ; i < 12 ; i++ ) {
+ sum += *(numbers.begin( ) + i ) * *(multipliers.begin( ) + i) ;
+ }
+ int check = 10 - ( sum % 10 ) ;
+ if ( check == 10 )
+ check == 0 ;
+ std::cout << "The ISBN is " << isbn << std::to_string( check ) << " !\n" ;
+ return 0 ;
+}
diff --git a/challenge-162/ulrich-rieke/haskell/ch-1.hs b/challenge-162/ulrich-rieke/haskell/ch-1.hs
new file mode 100644
index 0000000000..b69da0ddb8
--- /dev/null
+++ b/challenge-162/ulrich-rieke/haskell/ch-1.hs
@@ -0,0 +1,29 @@
+module Challenge162
+ where
+import Data.Char ( digitToInt )
+import Data.List.Split ( splitOn )
+
+askForISBN :: IO (String , String)
+askForISBN = do
+ putStrLn "Enter an ISBN string, with 12 digits only!"
+ isbn <- getLine
+ let numberstrings = splitOn "-" isbn
+ totalNumber = foldl1 ( ++ ) numberstrings
+ if length totalNumber == 12
+ then return (isbn , totalNumber)
+ else do
+ askForISBN
+
+multipliers :: [Int]
+multipliers = take 12 $ cycle [1 , 3 ]
+
+findDigitStr :: String -> String
+findDigitStr numberstring = if (10 - theSum) /= 0 then show (10 - theSum) else "0"
+where
+ theSum :: Int
+ theSum = mod (sum $ zipWith ( + ) ( map digitToInt numberstring ) multipliers) 10
+
+main :: IO ( )
+main = do
+ ( isbn , numbers ) <- askForISBN
+ putStrLn ("The complete ISBN is " ++ isbn ++ ( findDigitStr numbers) ++ " !")
diff --git a/challenge-162/ulrich-rieke/haskell/ch-2.hs b/challenge-162/ulrich-rieke/haskell/ch-2.hs
new file mode 100644
index 0000000000..f88666e6b8
--- /dev/null
+++ b/challenge-162/ulrich-rieke/haskell/ch-2.hs
@@ -0,0 +1,148 @@
+module Challenge162_2
+ where
+import Data.List.Split( chunksOf , splitOn )
+import Data.List ( elemIndex , nub , (!!) , (\\) , group , intercalate )
+import Data.Maybe ( fromJust )
+
+makeGrid :: String -> String
+makeGrid seedPhrase = phrase ++ ( alphabet \\ phrase )
+where
+ phrase :: String
+ phrase = nub $ foldl1 ( ++ ) $ splitOn " " seedPhrase
+ alphabet :: String
+ alphabet = ['a' .. 'i'] ++ ['k' .. 'z']
+
+--given a position number , in which row of the grid are we ?
+findRow :: Int -> Int
+findRow n = div ( n - ( mod n 5 )) 5
+
+--given a position number , in which column of the grid are we ?
+findColumn :: Int -> Int
+findColumn n = mod n 5
+
+encodeOnSameRow :: String -> Char -> Char
+encodeOnSameRow keyphrase letter = if findRow ( pos + 1 ) == findRow pos
+then keyphrase !! ( pos + 1 ) else keyphrase !! ( pos - 4 )
+where
+ pos :: Int
+ pos = fromJust $ elemIndex letter keyphrase
+
+encodeOnSameColumn :: String -> Char -> Char
+encodeOnSameColumn keyphrase letter
+ |pos + 5 > 25 = keyphrase !! ( mod pos 5 )
+ |otherwise = keyphrase !! ( pos + 5 )
+ where
+ pos :: Int
+ pos = fromJust $ elemIndex letter keyphrase
+
+encodeOnRectangle :: String -> String -> String
+encodeOnRectangle keyPhrase toBeEncrypted = [keyPhrase !! ( row1 * 5 + col2 ),
+ keyPhrase !! (row2 * 5 + col1)]
+ where
+ pos1 :: Int
+ pos1 = fromJust $ elemIndex ( head toBeEncrypted ) keyPhrase
+ pos2 :: Int
+ pos2 = fromJust $ elemIndex ( last toBeEncrypted ) keyPhrase
+ row1 :: Int
+ row1 = findRow pos1
+ row2 :: Int
+ row2 = findRow pos2
+ col1 :: Int
+ col1 = findColumn pos1
+ col2 :: Int
+ col2 = findColumn pos2
+
+decodeOnSameRow :: String -> Char -> Char
+decodeOnSameRow keyPhrase letter = if findRow ( pos - 1 ) == findRow pos
+then keyPhrase !! ( pos - 1 ) else keyPhrase !! ( pos + 4 )
+where
+ pos :: Int
+ pos = fromJust $ elemIndex letter keyPhrase
+
+decodeOnSameColumn :: String -> Char -> Char
+decodeOnSameColumn keyPhrase letter
+ |pos - 5 < 0 = keyPhrase !! ( 20 + findColumn pos )
+ |otherwise = keyPhrase !! ( pos - 5 )
+ where
+ pos :: Int
+ pos = fromJust $ elemIndex letter keyPhrase
+
+decodeOnRectangle :: String -> String -> String
+decodeOnRectangle keyPhrase toBeDecrypted = [keyPhrase !! (row1 * 5 + col2) ,
+keyPhrase !! (row2 * 5 + col1)]
+where
+ pos1 :: Int
+ pos1 = fromJust $ elemIndex ( head toBeDecrypted ) keyPhrase
+ pos2 :: Int
+ pos2 = fromJust $ elemIndex ( last toBeDecrypted ) keyPhrase
+ row1 :: Int
+ row1 = findRow pos1
+ row2 :: Int
+ row2 = findRow pos2
+ col1 :: Int
+ col1 = findColumn pos1
+ col2 :: Int
+ col2 = findColumn pos2
+
+substitute :: String -> Char -> Char -> String
+substitute word from to = map (\c -> if c == from then to else c ) word
+
+insertAfterDoubleLetters :: String -> String
+insertAfterDoubleLetters str = foldl1 ( ++ ) $ map (\li -> if length li > 1
+then intercalate "x" $ map (\c -> [c]) li else li) $ group str
+
+hackApart :: String -> [String]
+hackApart word
+ |odd $ length word = map (\li -> if head li == last li then [head li , 'x']
+ else li) $ chunksOf 2 ( word ++ ['x'] )
+ |otherwise = map (\li -> if head li == last li then [head li , 'x'] else
+ li) $ chunksOf 2 word
+
+encrypt :: String -> String -> String
+encrypt keyPhrase toBeEncrypted = foldl1 (++) $ map(\li -> encryptPair li ) $
+hackApart toBeEncrypted
+where
+ encryptPair :: String -> String
+ encryptPair pair
+ |findColumn pos1 == findColumn pos2 = map (\c -> encodeOnSameColumn keyPhrase c)
+ pair
+ |findRow pos1 == findRow pos2 = map (\c -> encodeOnSameRow keyPhrase c) pair
+ |otherwise = encodeOnRectangle keyPhrase pair
+ where
+ pos1 :: Int
+ pos1 = fromJust $ elemIndex ( head pair ) keyPhrase
+ pos2 :: Int
+ pos2 = fromJust $ elemIndex ( last pair ) keyPhrase
+
+decrypt :: String -> String -> String
+decrypt keyPhrase toBeDecrypted = foldl1 (++) $ map (\li -> decryptPair li ) $
+hackApart toBeDecrypted
+where
+ decryptPair :: String -> String
+ decryptPair pair
+ |findColumn pos1 == findColumn pos2 = map (\c -> decodeOnSameColumn keyPhrase
+ c) pair
+ |findRow pos1 == findRow pos2 = map (\c -> decodeOnSameRow keyPhrase c ) pair
+ |otherwise = decodeOnRectangle keyPhrase pair
+ where
+ pos1 :: Int
+ pos1 = fromJust $ elemIndex ( head pair ) keyPhrase
+ pos2 :: Int
+ pos2 = fromJust $ elemIndex ( last pair ) keyPhrase
+
+main :: IO ( )
+main = do
+ putStrLn "Please enter a key phrase from which to construct the grid!"
+ phrase <- getLine
+ putStrLn "Which text do you want to encrypt?"
+ toBeEncrypted <- getLine
+ let grid = makeGrid phrase
+ toBeEncryptedRed = insertAfterDoubleLetters $ substitute ( foldl1 ( ++ )
+ $ splitOn " " toBeEncrypted) 'j' 'i'
+ putStrLn toBeEncryptedRed
+ putStrLn $ encrypt grid toBeEncryptedRed
+ putStrLn "Enter another key phrase!"
+ secondPhrase <- getLine
+ putStrLn "Which text do you want to decrypt?"
+ toBeDecrypted <- getLine
+ putStrLn $ decrypt (makeGrid secondPhrase) toBeDecrypted
diff --git a/challenge-162/ulrich-rieke/perl/ch-1.pl b/challenge-162/ulrich-rieke/perl/ch-1.pl
new file mode 100644
index 0000000000..4156b11cd7
--- /dev/null
+++ b/challenge-162/ulrich-rieke/perl/ch-1.pl
@@ -0,0 +1,30 @@
+#!/usr/bin/perl ;
+use strict ;
+use warnings ;
+use feature 'say' ;
+
+say "Enter an ISBN with only 12 digits!" ;
+my $isbn = <STDIN> ;
+chomp $isbn ;
+my $converted = $isbn ;
+$converted =~ s/\D//g ;
+while ( length $converted != 12 ) {
+ say "For the purposes of this exercise, the ISBN should only have 12 digits!" ;
+ $isbn = <STDIN> ;
+ $converted = $isbn ;
+ $converted =~ s/\D//g ;
+}
+my @multipliers ;
+for (1 .. 6 ) {
+ push @multipliers , 1 , 3 ;
+}
+my @numbers = split( // , $converted ) ;
+my $sum = 0 ;
+for my $i ( 0 .. 11 ) {
+ $sum += $numbers[ $i ] * $multipliers[ $i ] ;
+}
+my $check = 10 - ( $sum % 10 ) ;
+if ( $check == 10 ) {
+ $check = 0 ;
+}
+say "The correct ISBN number is $isbn" . $check . " !" ;
diff --git a/challenge-162/ulrich-rieke/raku/ch-1.raku b/challenge-162/ulrich-rieke/raku/ch-1.raku
new file mode 100644
index 0000000000..66a23a837f
--- /dev/null
+++ b/challenge-162/ulrich-rieke/raku/ch-1.raku
@@ -0,0 +1,23 @@
+use v6 ;
+
+say "Enter an ISBN code without the last digit!" ;
+my $isbn = $*IN.get ;
+my $converted = $isbn ;
+$converted ~~ s:g/\D// ;
+while ( $converted.chars != 12 ) {
+ say "The ISBN code should only contain 12 digits for this exercise!" ;
+ $isbn = $*IN.get ;
+ $converted = $isbn ;
+ $converted ~~ s:g/\D// ;
+}
+my @numbers = $converted.comb.map( {.Int} ) ;
+my @multipliers ;
+for (1 .. 6 ) {
+ @multipliers.push( 1 , 3 ) ;
+}
+my $sum = sum( @numbers Z* @multipliers ) ;
+my $check = 10 - ($sum % 10) ;
+if ( $check == 10 ) {
+ $check = 0 ;
+}
+say "The correct ISBN number is " ~ ($isbn ~ ~$check) ~ " !" ;
diff --git a/challenge-162/ulrich-rieke/raku/ch-2.raku b/challenge-162/ulrich-rieke/raku/ch-2.raku
new file mode 100644
index 0000000000..63a402914a
--- /dev/null
+++ b/challenge-162/ulrich-rieke/raku/ch-2.raku
@@ -0,0 +1,199 @@
+use v6 ;
+
+sub createGridWord( Str $seedphrase is copy ) {
+ my %lettercount ;
+ my @alphabet = ('a' ..'i').Array ;
+ my @secondPart = ('k' .. 'z').Array ;
+ for @secondPart -> $let {
+ @alphabet.push( $let ) ;
+ }
+ for @alphabet -> $let {
+ %lettercount{ $let } = 0 ;
+ }
+ my @gridLetters ;
+ $seedphrase ~~ s:g/\s// ;
+ for ( $seedphrase.comb ) -> $let {
+ if ( %lettercount{ $let } == 0 ) {
+ @gridLetters.push( $let ) ;
+ %lettercount{ $let } = 1 ;
+ }
+ }
+ for @alphabet -> $let {
+ if ( %lettercount{ $let } == 0 ) {
+ @gridLetters.push( $let ) ;
+ }
+ }
+ return @gridLetters.join( ) ;
+}
+
+#which row in the grid is the number in ?
+sub findRow( Int $n is copy --> Int ) {
+ return ($n - ( $n % 5 )) div 5 ;
+}
+
+#which column in the grid is the number in?
+sub findColumn( Int $n --> Int ) {
+ return $n % 5 ;
+}
+
+#rule if both letters of a pair are on the same row
+sub encodeOnSameRow( Str $keyPhrase , Str $letter --> Str ) {
+ my $pos = $keyPhrase.index( $letter ) ;
+ if ( findRow( $pos + 1 ) == findRow( $pos ) ) {
+ return $keyPhrase.substr( $pos + 1 , 1 ) ;
+ }
+ else {
+ return $keyPhrase.substr( $pos - 4 , 1 ) ;
+ }
+}
+
+#rule if both letters of a pair are on the same column
+sub encodeOnSameColumn( Str $keyPhrase , Str $letter --> Str ) {
+ my $pos = $keyPhrase.index( $letter ) ;
+ if ( $pos + 5 > 25 ) {
+ return $keyPhrase.substr( $pos % 5 , 1 ) ;
+ }
+ else {
+ return $keyPhrase.substr( $pos + 5 , 1 ) ;
+ }
+}
+
+#the rule if a rectangle in the keyword grid is taken into account
+sub encodeOnRectangle( Str $keyPhrase , Str $pair --> Str ) {
+ my Str $encrypted ;
+ my Int $pos1 = $keyPhrase.index( $pair.substr( 0 , 1 )) ;
+ my Int $pos2 = $keyPhrase.index( $pair.substr( 1 , 1 )) ;
+ my Int $row1 = findRow( $pos1 ) ;
+ my Int $row2 = findRow( $pos2 ) ;
+ my Int $col1 = findColumn( $pos1 ) ;
+ my Int $col2 = findColumn( $pos2 ) ;
+ $encrypted ~= $keyPhrase.substr( $row1 * 5 + $col2 , 1 ) ;
+ $encrypted ~= $keyPhrase.substr( $row2 * 5 + $col1 , 1 ) ;
+ return $encrypted ;
+}
+
+#the following functions provide the return way of encoding
+sub decodeOnSameRow( Str $keyPhrase , Str $letter --> Str ) {
+ my Int $pos = $keyPhrase.index( $letter ) ;
+ my Str $decrypted ;
+ if ( findRow( $pos - 1 ) == findRow( $pos ) ) {
+ $decrypted = $keyPhrase.substr( $pos - 1 , 1 ) ;
+ }
+ else {
+ $decrypted = $keyPhrase.substr( $pos + 4 , 1 ) ;
+ }
+ return $decrypted ;
+}
+
+sub decodeOnSameColumn( Str $keyPhrase , Str $letter --> Str ) {
+ my Str $decrypted ;
+ my Int $pos = $keyPhrase.index( $letter ) ;
+ if ( $pos - 5 < 0 ) {
+ $decrypted = $keyPhrase.substr( 20 + findColumn( $pos ) , 1 ) ;
+ }
+ else {
+ $decrypted = $keyPhrase.substr( $pos - 5 , 1 ) ;
+ }
+ return $decrypted ;
+}
+
+sub decodeOnRectangle( Str $keyPhrase , Str $encoded --> Str ) {
+ my Str $decrypted ;
+ my Int $pos1 = $keyPhrase.index( $encoded.substr( 0 , 1 ) ) ;
+ my Int $pos2 = $keyPhrase.index( $encoded.substr( 1 , 1 )) ;
+ my Int $row1 = findRow( $pos1 ) ;
+ my Int $row2 = findRow( $pos2 ) ;
+ my Int $col1 = findColumn( $pos1 ) ;
+ my Int $col2 = findColumn( $pos2 ) ;
+ $decrypted ~= $keyPhrase.substr( $row1 * 5 + $col2 , 1 ) ;
+ $decrypted ~= $keyPhrase.substr( $row2 * 5 + $col1 , 1 ) ;
+ return $decrypted ;
+}
+
+#kind of composition of the above encoding functions
+sub encrypt( Str $keyPhrase , Str $toBeEncrypted is copy --> Str ) {
+ my Str $encrypted ;
+ my $len = $toBeEncrypted.chars ;
+ if ( not ( $len %% 2 ) ) {
+ $toBeEncrypted ~= "x" ;
+ }
+ my @pairs = $toBeEncrypted.comb.rotor( 2 ) ;
+ for @pairs -> $pair {
+ my Int $pos1 = $keyPhrase.index( $pair[0] ) ;
+ my Int $pos2 = $keyPhrase.index( $pair[1] ) ;
+ if ( findRow( $pos1 ) == findRow( $pos2 ) ) {
+ $encrypted ~= encodeOnSameRow( $keyPhrase , $pair[0] ) ;
+ $encrypted ~= encodeOnSameRow( $keyPhrase, $pair[1]) ;
+ }
+ elsif ( findColumn( $pos1 ) == findColumn( $pos2 ) ) {
+ $encrypted ~= encodeOnSameColumn( $keyPhrase, $pair[ 0 ] ) ;
+ $encrypted ~= encodeOnSameColumn( $keyPhrase , $pair[1]) ;
+ }
+ else {
+ $encrypted ~= encodeOnRectangle( $keyPhrase , $pair[0] ~ $pair[1] ) ;
+ }
+ }
+ return $encrypted ;
+}
+
+#composition of the above decoding functions
+sub decrypt( Str $keyPhrase, Str $toBeDecrypted --> Str ) {
+ my Str $decrypted ;
+ my @pairs = $toBeDecrypted.comb.rotor( 2 ) ;
+ for @pairs -> $pair {
+ my Int $pos1 = $keyPhrase.index( $pair[0] ) ;
+ my Int $pos2 = $keyPhrase.index( $pair[1] ) ;
+ if ( findColumn( $pos1 ) == findColumn( $pos2 ) ) {
+ $decrypted ~= decodeOnSameColumn( $keyPhrase , $pair[0] ) ;
+ $decrypted ~= decodeOnSameColumn( $keyPhrase , $pair[1] ) ;
+ }
+ elsif ( findRow( $pos1 ) == findRow( $pos2 )) {
+ $decrypted ~= decodeOnSameRow( $keyPhrase , $pair[0] ) ;
+ $decrypted ~= decodeOnSameRow( $keyPhrase , $pair[1] ) ;
+ }
+ else {
+ $decrypted ~= decodeOnRectangle( $keyPhrase , $pair[0] ~ $pair[1] ) ;
+ }
+ }
+ return $decrypted ;
+}
+
+#if two neighbouring letters are the same we intercalate an 'x'
+sub intercalate( Str $word is copy --> Str ) {
+ my @letters = $word.comb ;
+ my Str $intercalated ;
+ my $len = $word.chars ;
+ for (0 .. $len - 2) -> $i {
+ if ( $word.substr( $i , 1 ) eq $word.substr( $i + 1 , 1 )) {
+ $intercalated ~= $word.substr( $i , 1 ) ;
+ $intercalated ~= 'x' ;
+ }
+ else {
+ $intercalated ~= $word.substr( $i , 1 ) ;
+ }
+ }
+ return $intercalated ;
+}
+
+say "Please enter a key phrase:" ;
+my Str $keyPhrase = $*IN.get ;
+$keyPhrase ~~ s:g/'j'/'i'/ ;#j is taken for an i
+my Str $gridWord = createGridWord( $keyPhrase ) ;
+say "Please enter a string you want to encode:" ;
+my Str $forEncryption = $*IN.get ;
+$forEncryption ~~ s:g/'j'/'i'/ ;
+$forEncryption ~~ s:g/\s// ;
+my Int $len = $forEncryption.chars ;
+if ( not ( $len %% 2 ) ) {
+ $forEncryption ~= "x" ;
+}
+if ( $forEncryption ~~ /(.)$0/ ) {
+ $forEncryption = intercalate( $forEncryption ) ;
+}
+say "The encrypted string is " ~ (encrypt( $gridWord , $forEncryption )) ~ " !" ;
+say "Enter another key phrase!" ;
+$keyPhrase = $*IN.get ;
+$gridWord = createGridWord( $keyPhrase ) ;
+say "Please enter a string you want to decode:" ;
+my Str $forDecryption = $*IN.get ;
+say "The decrypted string is " ~ (decrypt( $gridWord , $forDecryption )) ~ " !" ;