Prefer snake-shift instead of a row-by-row shift

Per the assignment's instructions, the `Shift n` operation should treat
the *entire keyboard* like a cycle and shift that. I was erroneously
treating *each row* like a cycle and shifting those one-by-one.

This change fixes that. In addition, it also:
- Updates README.md with expected inputs and outputs
- Updates test suite
- Adds `split` dependency to {default,shell}.nix
This commit is contained in:
William Carroll 2020-08-12 12:03:35 +01:00
parent f11b91c985
commit bba3f16c43
5 changed files with 57 additions and 37 deletions

View file

@ -7,14 +7,31 @@ import Utils ((|>))
import qualified Data.Char as Char
import qualified Utils
import qualified Data.List.Split as Split
import qualified Keyboard
import qualified Data.HashMap.Strict as HM
--------------------------------------------------------------------------------
transform :: Keyboard -> Transform -> Keyboard
transform (Keyboard xs) HorizontalFlip = xs |> fmap reverse |> Keyboard
transform (Keyboard xs) VerticalFlip = xs |> reverse |> Keyboard
transform (Keyboard xs) (Shift n) = xs |> fmap (Utils.rotate n) |> Keyboard
transform (Keyboard xs) xform =
case xform of
HorizontalFlip ->
xs
|> fmap reverse
|> Keyboard
VerticalFlip ->
xs
|> reverse
|> Keyboard
Shift n ->
xs
|> concat
|> Utils.rotate n
|> Split.chunksOf 10
|> Keyboard
retypePassage :: String -> Keyboard -> Maybe String
retypePassage passage newKeyboard =

View file

@ -57,11 +57,11 @@ Now a working example:
$ ./result/transform-keyboard --transforms=HHVS12VHVHS3 --passage='Hello,Brilliant.'
Typing: "Hello,Brilliant."
On this keyboard:
[N][M][,][.][/][Z][X][C][V][B]
[H][J][K][L][;][A][S][D][F][G]
[Y][U][I][O][P][Q][W][E][R][T]
[6][7][8][9][0][1][2][3][4][5]
Result: QKRRF30LDRRDY1;4
[H][J][K][L][;][Q][W][E][R][T]
[Y][U][I][O][P][1][2][3][4][5]
[6][7][8][9][0][Z][X][C][V][B]
[N][M][,][.][/][A][S][D][F][G]
Result: ZIVV4D/O3VV36APF
```
...and an example with an erroneous input (i.e. `!`):
@ -70,10 +70,10 @@ Result: QKRRF30LDRRDY1;4
$ ./result/transform-keyboard --transforms=HHVS12VHVHS3 --passage='Hello,Brilliant!'
Typing: "Hello,Brilliant!"
On this keyboard:
[N][M][,][.][/][Z][X][C][V][B]
[H][J][K][L][;][A][S][D][F][G]
[Y][U][I][O][P][Q][W][E][R][T]
[6][7][8][9][0][1][2][3][4][5]
[H][J][K][L][;][Q][W][E][R][T]
[Y][U][I][O][P][1][2][3][4][5]
[6][7][8][9][0][Z][X][C][V][B]
[N][M][,][.][/][A][S][D][F][G]
Looks like at least one of the characters in your input passage doesn't fit on our QWERTY keyboard:
[1][2][3][4][5][6][7][8][9][0]
[Q][W][E][R][T][Y][U][I][O][P]

View file

@ -5,11 +5,12 @@ import Test.Hspec
import Test.QuickCheck
import Keyboard (Keyboard(..))
import Transforms (Transform(..))
import Data.Coerce
import Utils
import qualified App
import qualified Keyboard
import qualified Transforms
import qualified Utils
--------------------------------------------------------------------------------
main :: IO ()
@ -55,12 +56,12 @@ main = hspec $ do
it "shifts any keyboard" $ do
property $ \first second third fourth n ->
App.transform (Keyboard [first, second, third, fourth]) (Shift n) == do
Keyboard $ [ Utils.rotate n first
, Utils.rotate n second
, Utils.rotate n third
, Utils.rotate n fourth
]
App.transform (Keyboard [first, second, third, fourth]) (Shift n)
|> (coerce :: Keyboard -> [[Char]])
|> concat ==
[first, second, third, fourth]
|> concat
|> Utils.rotate n
it "flips a QWERTY keyboard horizontally" $ do
App.transform Keyboard.qwerty HorizontalFlip == do
@ -72,7 +73,7 @@ main = hspec $ do
it "flips a keyboard vertically" $ do
App.transform Keyboard.qwerty VerticalFlip == do
Keyboard $ [ ['Z','X','C','V','B','N','M',',','.','/']
Keyboard [ ['Z','X','C','V','B','N','M',',','.','/']
, ['A','S','D','F','G','H','J','K','L',';']
, ['Q','W','E','R','T','Y','U','I','O','P']
, ['1','2','3','4','5','6','7','8','9','0']
@ -80,18 +81,18 @@ main = hspec $ do
it "shifts a keyboard left N times" $ do
App.transform Keyboard.qwerty (Shift 2) == do
Keyboard $ [ ['3','4','5','6','7','8','9','0','1','2']
, ['E','R','T','Y','U','I','O','P','Q','W']
, ['D','F','G','H','J','K','L',';','A','S']
, ['C','V','B','N','M',',','.','/','Z','X']
Keyboard [ ['3','4','5','6','7','8','9','0','Q','W']
, ['E','R','T','Y','U','I','O','P','A','S']
, ['D','F','G','H','J','K','L',';','Z','X']
, ['C','V','B','N','M',',','.','/','1','2']
]
it "shifts right negative amounts" $ do
App.transform Keyboard.qwerty (Shift (-3)) == do
Keyboard $ [ ['8','9','0','1','2','3','4','5','6','7']
, ['I','O','P','Q','W','E','R','T','Y','U']
, ['K','L',';','A','S','D','F','G','H','J']
, [',','.','/','Z','X','C','V','B','N','M']
Keyboard [ [',','.','/','1','2','3','4','5','6','7']
, ['8','9','0','Q','W','E','R','T','Y','U']
, ['I','O','P','A','S','D','F','G','H','J']
, ['K','L',';','Z','X','C','V','B','N','M']
]
describe "Transforms.optimize" $ do

View file

@ -5,9 +5,10 @@ let
rev = "afa9ca61924f05aacfe495a7ad0fd84709d236cc";
}) {};
ghc = pkgs.haskellPackages.ghcWithPackages (hpkgs: [
hpkgs.optparse-applicative
hpkgs.unordered-containers
ghc = pkgs.haskellPackages.ghcWithPackages (hpkgs: with hpkgs; [
optparse-applicative
unordered-containers
split
]);
in pkgs.stdenv.mkDerivation {
name = "transform-keyboard";

View file

@ -10,6 +10,7 @@ in pkgs.mkShell {
hspec
optparse-applicative
unordered-containers
split
]))
];
}