Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crypto-square: Rewrite it to match x-common or to be more idiomatic. #259

Closed
rbasso opened this issue Aug 7, 2016 · 5 comments
Closed
Labels

Comments

@rbasso
Copy link
Contributor

rbasso commented Aug 7, 2016

The way it is now, crypto-square has some problems:

  • The functions' names are not very descriptive and do not match what is is x-common.
  • The last - commented out - test expects a string representing a matrix, with spaces used for separating rows and representing missing elements. This was specified in x-common/crypto-square.json, but seems so badong...

At least, we need to review the functions' names.

Related to #194 and exercism/problem-specifications#356.

Important: This exercise was changed in branch hspec-fail-fast by #249 . Please use that branch for any PR related to it or wait until it's merged in master.

@rbasso rbasso changed the title crypto-square: Rewrite to make it more idiomatic. crypto-square: Rewrite it to match x-common or to be more idiomatic. Sep 7, 2016
@rbasso
Copy link
Contributor Author

rbasso commented Oct 3, 2016

The JSON file

The reference canonical-data.json asks for 4 functions.

Ignoring the last test - that we'll discuss later - they are related like this:

normalizedPlaintext :: String -> String

plaintextSegments :: String -> [String]
plaintextSegments = toSquare . normalizedPlaintext

encoded :: String -> String
encoded = concat . transpose . plaintextSegments

ciphertext :: String -> String
ciphertext = unwords . transpose . plaintextSegments

Why not?

  • Each function is defined as a transformation over a previous function. A better design would expose the building blocks, not their combinations.
  • Because of the above, the functions' names are not very descriptive.
  • encoded is not needed for ciphertext.

En example solution to the exercise

The above design seems unidiomatic in a language where function composition is so easy. A more idiomatic solution would be:

normalize :: String -> String

toSquare :: [a] -> [[a]]

encode :: String -> String
encode = unwords . transpose . toSquare . normalize

Padding

The last test checks the padding of the "words" outputted by ciphertext.

This is not mentioned in description.md and also makes no sense IMHO:

  • If the output represents a rectangle, it could be a list of unpadded Strings.
  • If if represents an encoded text separated in blocks by spaces, a single space is enough.
  • The spaces in the output String should not be at the same time padding and separators.

What do we have now?

In the Haskell track, currently we ask for the functions:

normalizePlaintext :: String -> String -- Just missing a 'd' in the name.

plaintextSegments :: String -> [String] -- Matches the JSON file.
plaintextSegments = toSquare . normalizePlaintext

ciphertext :: String -> String -- Matches `encoded` from the JSON file.
ciphertext = concat . transpose . plaintextSegments

normalizeCiphertext :: String -> String -- Matches `ciphertext` from them JSON file, without testing for padding.
normalizeCiphertext = unwords . transpose . plaintextSegments

What should we do?

@rbasso rbasso added the question label Oct 3, 2016
@petertseng
Copy link
Member

Ruby also wishes changes to their crypto-square exercism/ruby#422

Either way, should we fix the problem at the source by changing canonical-data.json?

Especially if the intermediate functions are removed, we will have a lot more freedom, since we can ask for less.

@rbasso
Copy link
Contributor Author

rbasso commented Oct 4, 2016

Reading exercism/problem-specifications#250, it seems that keeping the intermediary functions was not an unpopular decision at the time. so I'm not sure if people will agree with removing them.

Anyway, we are not alone in the feeling that they are undesirable but, if we remove the intermediary tests, only three test will remain, and one of them has space-padded words. We need more comprehensive tests.

Ignoring the JSON file or a while, we could imagine a completely new test suite...

How could it be?

Given a list of input-output pairs for the encoding function, we could progressively test the following:

  • Is the set of output characters correct?
  • Is the multiset of output characters correct?
  • The encoded message has the all the non-space characters in the correct order?
  • Is the output message correctly separated in blocks?
  • Are the blocks separated by a single space?
  • Is the output string exactly as expected?

I think that the last two test should could be avoided.

This plan would add a lot o complexity to the tests, but it would keep a progression similar to the one using intermediary functions.

Is it too crazy?

@petertseng
Copy link
Member

It sounds like the tests you describe will be test for particular properties of the outputs, rather than specific values! It's interesting because exercism/problem-specifications#191 was intended to be that sort of exercise as well. I'd be interested to see one.

@rbasso
Copy link
Contributor Author

rbasso commented Oct 5, 2016

The "design" came out this way for two reasons:

  • To avoid testing for intermediary functions.
  • To avoid testing for equality on the output.

Instead of over-specifying the tests, the idea was to test progressively until it have the minimum desired behavior.

@rbasso rbasso closed this as completed Oct 9, 2016
petertseng pushed a commit to ashaindlin/haskell that referenced this issue Aug 1, 2021
Fixes exercism#895, the complaint that
the whitespace was being ignored.

The canonical test data itself is fine; the problem was that the test
suite was ignoring whitespace when comparing the actual result to the
expected result.

The decision to ignore whitespace was a originally deliberate decision,
with the reasoning in exercism#259.

However, maintainers' current judgment is that as long as our output is
a String, it's better to keep it as the problem description says, for it
would be against the description if a student emitted an output with a
lot of leading spaces (among others).

If the track changes the output to a [String], then the maintainers
could freely choose whether to require the trailing spaces or forbid
them.
petertseng pushed a commit to ashaindlin/haskell that referenced this issue Aug 1, 2021
Fixes exercism#895, the complaint that
the whitespace was being ignored.

The canonical test data itself is fine; the problem was that the test
suite was ignoring whitespace when comparing the actual result to the
expected result.

The decision to ignore whitespace was a originally deliberate decision,
with the reasoning in exercism#259.

However, maintainers' current judgment is that as long as our output is
a String, it's better to keep it as the problem description says, for it
would be against the description if a student emitted an output with a
lot of leading spaces (among others).

If the track changes the output to a [String], then the maintainers
could freely choose whether to require the trailing spaces or forbid
them.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants