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

add variable-length-quantity exercise #427

Merged
merged 4 commits into from
Jul 4, 2024

Conversation

kmarker1101
Copy link
Contributor

I went with a difficulty of 6. In Racket it is an 8 which seems a little high. It is a 4 in python.

@kmarker1101 kmarker1101 changed the title add variable-lenght-quantity exercise add variable-length-quantity exercise Jun 29, 2024
@BNAndras BNAndras added x:module/practice-exercise Work on Practice Exercises x:rep/large Large amount of reputation labels Jun 29, 2024
@BNAndras
Copy link
Member

I’ve never done this particular exercise so I’ll defer to @fapdash, but would hexadecimal literals be more appropriate here for the tests?

@kmarker1101
Copy link
Contributor Author

OK, it looks like racket does not do this, they just use the integer tests. Python does use hex though.

def test_maximum_32_bit_integer_input(self):
        self.assertEqual(encode([0xFFFFFFFF]), [0x8F, 0xFF, 0xFF, 0xFF, 0x7F])

As the instructions show examples in hex, it probably makes more sense to use hex.

@kmarker1101
Copy link
Contributor Author

Example solution using hex.

(define-error 'incomplete "incomplete sequence")

(defun encode (hex-numbers)
  "Encode a list of hexadecimal numbers into VLQ format, returning a list of hexadecimal values."
  (let ((encode-single (lambda (number)
                         (let ((byte-string (list (logand number #x7F)))) ; Initialize with the least significant byte
                           (setq number (lsh number -7)) ; Shift right before the loop
                           (while (> number 0)
                             (push (logior (logand number #x7F) #x80) byte-string)
                             (setq number (lsh number -7)))
                           byte-string))))
    (apply #'append (mapcar encode-single hex-numbers))))

(defun decode (hex-values)
  "Decode a list of hexadecimal values from VLQ format into hexadecimal numbers."
  (let ((values '())
        (number 0)
        (incomplete t))
    (dolist (byte hex-values)
      (setq number (lsh number 7))
      (setq number (logior number (logand byte #x7F)))
      (if (= (logand byte #x80) 0)
          (progn
            (setq values (cons number values))
            (setq number 0)
            (setq incomplete nil))
        (setq incomplete t)))
    (if incomplete
        (signal 'incomplete 'nil)
      (reverse values))))

(ert-deftest largest-triple-byte ()
  (should (equal (encode '(#x1FFFFF)) '(#xFF #xFF #x7F))))

(ert-deftest largest-triple-byte-decode ()
  (should (equal (decode '(#xFF #xFF #x7F)) '(#x1FFFFF))))

Copy link
Contributor

@fapdash fapdash left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Besides the removal error stub I think we can merge like that.
The error message doesn't change if we change the code to use hex representation, it gets parsed to integer either way. The error message already displays the hex and the integer representation:

Test largest-triple-byte condition:
    (ert-test-failed
     ((should
       (equal
        (encode ...)
        '(255 255 122)))
      :form
      (equal
       (255 255 127)
       (255 255 122))
      :value nil :explanation
      (list-elt 2
                (different-atoms
                 (127 "#x7f" "?\177")
                 (122 "#x7a" "?z")))))

@kmarker1101 I also never implemented this exercise before so I'd leave it up to you, if you think the student benefits from looking at the test code and seeing hex numbers then do the change, otherwise we keep the test code as it is right now.



(define-error 'incomplete
(error "Delete this S-Expression and write your own implementation"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want the students to provide a specific error message then you can test for it with the following pattern:

(ert-deftest encode-with-a-not-coprime-to-m ()
(let ((error-data
(should-error
(encode "This is a test." '(("a" . 6) ("b" . 17))))))
(should
(string=
"a and m must be coprime." (error-message-string error-data)))))

But I don't think it's necessary to expect a specific error message. In the past we didn't define-error in the stub file so just delete Line 8-9.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I will change to use hex, mainly because the instructions examples use hex. Thanks

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing for specific errors started in #400 where it made sense to distinguish between the two errors. We did the same on Racket for that exercise even though generally we avoid testing for specific errors there because students often raise a contract violation (more idiomatic) than an error.

Here, there’s only one error so yeah we don’t need that specificity.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kind of like testing for a specific error type, imo it's a good habit to get into to signal specific errors instead of the generic error type. My comment referred to testing for a specific error message.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be good now I think

@kmarker1101
Copy link
Contributor Author

@BNAndras should be ready

@BNAndras
Copy link
Member

BNAndras commented Jul 3, 2024

If you take a look at those two literals, I'd appreciate it. Otherwise, it looks good to me.

@kmarker1101 kmarker1101 requested a review from fapdash July 4, 2024 11:56
@BNAndras BNAndras merged commit fda7741 into exercism:main Jul 4, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
x:module/practice-exercise Work on Practice Exercises x:rep/large Large amount of reputation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants