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:
		
							parent
							
								
									f11b91c985
								
							
						
					
					
						commit
						bba3f16c43
					
				
					 5 changed files with 57 additions and 37 deletions
				
			
		|  | @ -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 = | ||||
|  |  | |||
|  | @ -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] | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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"; | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ in pkgs.mkShell { | |||
|       hspec | ||||
|       optparse-applicative | ||||
|       unordered-containers | ||||
|       split | ||||
|     ])) | ||||
|   ]; | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue