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

all-your-base: sync #1955

Merged
merged 1 commit into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ There are some custom tera filters in [`rust-tooling`](/rust-tooling/generate/sr
Here's the hopefully up-to-date list:
- `to_hex` formats ints in hexadecimal
- `snake_case` massages an arbitrary string into a decent Rust identifier
- `make_test_ident` is like snake case, but prepends `test_` if the string starts with a digit
- `fmt_num` format number literals (insert `_` every third digit)

Feel free to add your own in the crate `rust-tooling`.
Expand Down
26 changes: 26 additions & 0 deletions exercises/practice/all-your-base/.meta/test_template.tera
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use allyourbase as ayb;

{% for test in cases %}
#[test]
#[ignore]
fn {{ test.description | make_test_ident }}() {
let input_base = {{ test.input.inputBase }};
let input_digits = &{{ test.input.digits | json_encode() }};
let output_base = {{ test.input.outputBase }};
{%- if not test.expected is object %}
let output_digits = vec!{{ test.expected | json_encode() }};
{%- endif %}
assert_eq!(
ayb::convert(input_digits, input_base, output_base),
{%- if not test.expected is object %}
Ok(output_digits)
{%- elif test.expected.error == "input base must be >= 2" %}
Err(ayb::Error::InvalidInputBase)
{%- elif test.expected.error == "all digits must satisfy 0 <= d < input base" %}
Err(ayb::Error::InvalidDigit(2))
{%- elif test.expected.error == "output base must be >= 2" %}
Err(ayb::Error::InvalidOutputBase)
{%- endif %}
);
}
{% endfor -%}
36 changes: 33 additions & 3 deletions exercises/practice/all-your-base/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# This is an auto-generated file. Regular comments will be removed when this
# file is regenerated. Regenerating will not touch any manually added keys,
# so comments can be added in a "comment" key.
# This is an auto-generated file.
#
# Regenerating this file via `configlet sync` will:
# - Recreate every `description` key/value pair
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
# - Preserve any other key/value pair
#
# As user-added comments (using the # character) will be removed when this file
# is regenerated, comments can be added via a `comment` key.

[5ce422f9-7a4b-4f44-ad29-49c67cb32d2c]
description = "single bit one to decimal"
Expand All @@ -23,6 +30,9 @@ description = "trinary to hexadecimal"
[d3901c80-8190-41b9-bd86-38d988efa956]
description = "hexadecimal to trinary"

[5d42f85e-21ad-41bd-b9be-a3e8e4258bbf]
description = "15-bit integer"

[d68788f7-66dd-43f8-a543-f15b6d233f83]
description = "empty list"

Expand All @@ -41,6 +51,16 @@ description = "input base is one"
[e21a693a-7a69-450b-b393-27415c26a016]
description = "input base is zero"

[54a23be5-d99e-41cc-88e0-a650ffe5fcc2]
description = "input base is negative"
include = false
comment = "we use unsigned integers"

[9eccf60c-dcc9-407b-95d8-c37b8be56bb6]
description = "negative digit"
include = false
comment = "we use unsigned integers"

[232fa4a5-e761-4939-ba0c-ed046cd0676a]
description = "invalid positive digit"

Expand All @@ -49,3 +69,13 @@ description = "output base is one"

[73dac367-da5c-4a37-95fe-c87fad0a4047]
description = "output base is zero"

[13f81f42-ff53-4e24-89d9-37603a48ebd9]
description = "output base is negative"
include = false
comment = "we use unsigned integers"

[0e6c895d-8a5d-4868-a345-309d094cfe8d]
description = "both bases are negative"
include = false
comment = "we use unsigned integers"
32 changes: 16 additions & 16 deletions exercises/practice/all-your-base/tests/all-your-base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ fn hexadecimal_to_trinary() {

#[test]
#[ignore]
fn fifteen_bit_integer() {
fn test_15_bit_integer() {
let input_base = 97;
let input_digits = &[3, 46, 60];
let output_base = 73;
Expand Down Expand Up @@ -157,20 +157,20 @@ fn leading_zeros() {

#[test]
#[ignore]
fn invalid_positive_digit() {
let input_base = 2;
let input_digits = &[1, 2, 1, 0, 1, 0];
fn input_base_is_one() {
let input_base = 1;
let input_digits = &[0];
let output_base = 10;
assert_eq!(
ayb::convert(input_digits, input_base, output_base),
Err(ayb::Error::InvalidDigit(2))
Err(ayb::Error::InvalidInputBase)
);
}

#[test]
#[ignore]
fn input_base_is_one() {
let input_base = 1;
fn input_base_is_zero() {
let input_base = 0;
let input_digits = &[];
let output_base = 10;
assert_eq!(
Expand All @@ -181,25 +181,25 @@ fn input_base_is_one() {

#[test]
#[ignore]
fn output_base_is_one() {
fn invalid_positive_digit() {
let input_base = 2;
let input_digits = &[1, 0, 1, 0, 1, 0];
let output_base = 1;
let input_digits = &[1, 2, 1, 0, 1, 0];
let output_base = 10;
assert_eq!(
ayb::convert(input_digits, input_base, output_base),
Err(ayb::Error::InvalidOutputBase)
Err(ayb::Error::InvalidDigit(2))
);
}

#[test]
#[ignore]
fn input_base_is_zero() {
let input_base = 0;
let input_digits = &[];
let output_base = 10;
fn output_base_is_one() {
let input_base = 2;
let input_digits = &[1, 0, 1, 0, 1, 0];
let output_base = 1;
assert_eq!(
ayb::convert(input_digits, input_base, output_base),
Err(ayb::Error::InvalidInputBase)
Err(ayb::Error::InvalidOutputBase)
);
}

Expand Down
16 changes: 16 additions & 0 deletions rust-tooling/generate/src/custom_filters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type Filter = fn(&Value, &HashMap<String, Value>) -> Result<Value>;
pub static CUSTOM_FILTERS: &[(&str, Filter)] = &[
("to_hex", to_hex),
("snake_case", snake_case),
("make_test_ident", make_test_ident),
("fmt_num", fmt_num),
];

Expand All @@ -33,6 +34,21 @@ pub fn snake_case(value: &Value, _args: &HashMap<String, Value>) -> Result<Value
))
}

pub fn make_test_ident(value: &Value, _args: &HashMap<String, Value>) -> Result<Value> {
let value = snake_case(value, _args)?;
let Some(value) = value.as_str() else {
return Err(tera::Error::call_filter(
"make_test_ident filter expects a string",
"serde_json::value::Value::as_str",
));
};
if !value.chars().next().unwrap_or_default().is_alphabetic() {
// identifiers cannot start with digits etc.
return Ok(Value::String(format!("test_{value}")));
}
Ok(Value::String(value.into()))
}

pub fn fmt_num(value: &Value, _args: &HashMap<String, Value>) -> Result<Value> {
let Some(value) = value.as_number() else {
return Err(tera::Error::call_filter(
Expand Down