-
-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Welcome to tech palace (#342) [no important files changed]
* remove cars-assemble * init * introduction + new links for strings and felts * update prereq to arrays * update prereq to control-flow + move enums to rpn-calculator * start exemplar * implement exemplar * add hints * prerequisite `control-flow` instead of `array` * fix lint errors instructions.md * remove trailing space in introduction.md * Apply suggestions from code review Co-authored-by: András B Nagy <20251272+BNAndras@users.noreply.github.com> --------- Co-authored-by: András B Nagy <20251272+BNAndras@users.noreply.github.com>
- Loading branch information
Showing
12 changed files
with
437 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Hints | ||
|
||
## General | ||
|
||
- The [ByteArray][bytearray] type contains a few useful inbuilt methods, so you'll generally have to implement your own utility functions for manipulating ByteArrays. | ||
- `ByteArray` actually represents an array of bytes and not "chars" as in many other languages. | ||
- Working with both short and long strings at the same time can be challenging, so some helper functions are already implemented which you can use for this exercise. | ||
|
||
## 1. Create the welcome message | ||
|
||
- Strings can be concatenated using the `+` operator. | ||
- Check if you can use any of the helper functions. | ||
|
||
## 2. Add a fancy border | ||
|
||
- You can append `'*'` characters in a loop. | ||
- A newline is a special escape character. | ||
|
||
## 3. Clean up old marketing messages | ||
|
||
- Find the start and end indices of the clean message. | ||
- You will probably need to copy the clean message characters into a new ByteArray one by one. | ||
|
||
[bytearray]: https://docs.swmansion.com/scarb/corelib/core-byte_array-ByteArrayTrait.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# Instructions | ||
|
||
There is an appliance store called "Tech Palace" nearby. | ||
The owner of the store recently installed a big display to use for marketing messages and to show a special greeting when customers scan their loyalty cards at the entrance. | ||
The display consists of lots of small LED lights and can show multiple lines of text. | ||
|
||
The store owner needs your help with the code that is used to generate the text for the new display. | ||
|
||
## 1. Create the welcome message | ||
|
||
<!-- markdownlint-disable-next-line MD038 --> | ||
For most customers who scan their loyalty cards, the store owner wants to see `Welcome to the Tech Palace, ` followed by the name of the customer in capital letters on the display. | ||
|
||
Implement the function `welcome_message` that accepts the name of the customer as a short string (`felt252`) argument and returns the desired message as a `ByteArray`. | ||
|
||
```rust | ||
welcome_message("Judy") | ||
// => Welcome to the Tech Palace, JUDY | ||
``` | ||
|
||
## 2. Add a fancy border | ||
|
||
For loyal customers that buy a lot at the store, the owner wants the welcome display to be more fancy by adding a line of stars before and after the welcome message. | ||
They are not sure yet how many stars should be in the lines so they want that to be configurable. | ||
|
||
Write a function `add_border` that accepts a welcome message (a `ByteArray`) and the number of stars per line (type `u32`) as arguments. | ||
It should return a `ByteArray` that consists of 3 lines, a line with the desired number of stars, then the welcome message as it was passed in, then another line of stars. | ||
|
||
```rust | ||
add_border("Welcome!", 10) | ||
``` | ||
|
||
Should return the following: | ||
|
||
```bash | ||
********** | ||
Welcome! | ||
********** | ||
``` | ||
|
||
## 3. Clean up old marketing messages | ||
|
||
Before installing this new display, the store had a similar display that could only show non-configurable, static lines. | ||
The owner would like to reuse some of the old marketing messages on the new display. | ||
However, the data already includes a star border and some unfortunate whitespaces. | ||
Your task is to clean up the messages so they can be re-used. | ||
|
||
Implement a function `clean_up_message` that accepts the old marketing message as a `ByteArray`. | ||
The function should first remove all stars from the text and afterwards remove the leading and trailing whitespaces from the remaining text. | ||
The function should then return the cleaned up message. | ||
|
||
```rust | ||
let message: ByteArray = " | ||
************************** | ||
* BUY NOW, SAVE 10% * | ||
************************** | ||
"; | ||
|
||
clean_up_message(message) | ||
// => BUY NOW, SAVE 10% | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
# Introduction | ||
|
||
Cairo doesn't have a native type for strings but provides two ways to handle them: short strings using simple quotes and `ByteArray` using double quotes. | ||
|
||
A short string is an ASCII string where each character is encoded on one byte. | ||
|
||
The type Cairo uses for short strings by default is `felt252`, making their maximum length only 31 characters. | ||
|
||
```rust | ||
// below are different ways to write the same value | ||
let name: felt252 = 'Jane'; // short string format | ||
let name: felt252 = 0x4a616e65; // byte format | ||
let name: felt252 = 1247899237; // decimal format | ||
``` | ||
|
||
Technically, any integer type smaller than `felt252` can be represented using the short string format. | ||
|
||
```rust | ||
// all of the below are equal u8 values, they are just written using different formats! | ||
let lowercase_a_in_ascii: u8 = 'a'; // short string format | ||
let lowercase_a_in_ascii: u8 = 0x61; // byte format | ||
let lowercase_a_in_ascii: u8 = 97; // decimal format | ||
``` | ||
|
||
For strings longer than 31 characters Cairo provides `ByteArray`, which has an unlimited length. | ||
|
||
```rust | ||
let long_string: ByteArray = "this is a string which has more than 31 characters"; | ||
``` | ||
|
||
ByteArrays can be concatenated via the `+` operator: | ||
|
||
```rust | ||
"Jane" + " " + "Austen" | ||
// => "Jane Austen" | ||
``` | ||
|
||
Some special characters need to be escaped with a leading backslash, such as `\t` for a tab and `\n` for a new line in strings. | ||
|
||
```rust | ||
"How is the weather today?\nIt's sunny" | ||
// => | ||
// How is the weather today? | ||
// It's sunny | ||
``` | ||
|
||
You can even access individual bytes within a ByteArray using its index. | ||
|
||
Be careful though, the type of the returned byte is `u8` and not `ByteArray`! | ||
|
||
```rust | ||
let hello: ByteArray = "Hello World!"; | ||
let exclamation_mark: u8 = hello[11]; | ||
// => 33 | ||
``` | ||
|
||
The core library provides many useful methods and operators to work on ByteArrays. | ||
|
||
For more information about ByteArray methods, check out the [ByteArrayTrait documentation][docs]. | ||
|
||
Here are some examples: | ||
|
||
```rust | ||
let name: felt252 = 'Jane'; | ||
let mut greeting: ByteArray = "Welcome "; | ||
|
||
// append_word appends a single word of a given number of bytes to the end of the ByteArray | ||
greeting.append_word(name, 4); | ||
// => "Welcome Jane" | ||
|
||
// rev returns a ByteArray with the all characters reversed | ||
let rev_greeting = greeting.rev(); | ||
// => "enaJ emocleW" | ||
``` | ||
|
||
[docs]: https://docs.swmansion.com/scarb/corelib/core-byte_array-ByteArrayTrait.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# Design | ||
|
||
## Goal | ||
|
||
The goal of this exercise is to teach the student the basics of strings and the `strings` package in Go. | ||
|
||
## Learning objectives | ||
|
||
- Know how to define short strings | ||
- Know how to define Byte Array strings | ||
- Know how to concatenate different string types | ||
- Know how to use escape characters | ||
|
||
## Out of scope | ||
|
||
- String formatting | ||
|
||
## Concepts | ||
|
||
The Concepts this exercise unlocks are: | ||
|
||
- `strings` | ||
|
||
## Prerequisites | ||
|
||
- `control-flow` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// Returns a welcome message for the customer. | ||
pub fn welcome_message(customer: felt252) -> ByteArray { | ||
"Welcome to the Tech Palace, " + to_uppercase(customer.into()) | ||
} | ||
|
||
// Adds a border to a welcome message. | ||
pub fn add_border(welcome_msg: ByteArray, num_stars_per_line: u32) -> ByteArray { | ||
let mut border: ByteArray = ""; | ||
for _ in 0..num_stars_per_line { | ||
border.append_byte('*'); | ||
}; | ||
border.clone() + "\n" + welcome_msg + "\n" + border | ||
} | ||
|
||
// Cleans up an old marketing message. | ||
pub fn clean_up_message(old_msg: ByteArray) -> ByteArray { | ||
let mut start = 0; | ||
while is_whitespace(old_msg[start]) || old_msg[start] == '*' { | ||
start += 1; | ||
}; | ||
let mut end = old_msg.len(); | ||
while is_whitespace(old_msg[end - 1]) || old_msg[end - 1] == '*' { | ||
end -= 1; | ||
}; | ||
let mut clean_msg = ""; | ||
for i in start..end { | ||
clean_msg.append_byte(old_msg[i]); | ||
}; | ||
clean_msg | ||
} | ||
|
||
/////////////// | ||
/// Helpers /// | ||
/////////////// | ||
|
||
// Distance between a lowercase and uppercase representations | ||
// of the same character in the ASCII table | ||
const ASCII_CASE_OFFSET: u8 = 32; | ||
const BYTE_SIZE: u256 = 256; // 2^8, number of possible values in a byte | ||
const BYTE_MASK: u256 = 0xff; // Mask to extract the last byte (8 bits) | ||
|
||
fn to_uppercase(input: u256) -> ByteArray { | ||
let mut remaining_bytes = input; | ||
let mut uppercase_chars: ByteArray = ""; | ||
while remaining_bytes != 0 { | ||
uppercase_chars.append_byte(char_to_uppercase(get_last_byte(remaining_bytes))); | ||
remaining_bytes = remove_last_byte(remaining_bytes); | ||
}; | ||
uppercase_chars.rev() | ||
} | ||
|
||
fn get_last_byte(chars: u256) -> u8 { | ||
(chars & BYTE_MASK.into()).try_into().unwrap() | ||
} | ||
|
||
fn remove_last_byte(chars: u256) -> u256 { | ||
chars / BYTE_SIZE.into() | ||
} | ||
|
||
fn char_to_uppercase(c: u8) -> u8 { | ||
if is_lowercase(c) { | ||
c - ASCII_CASE_OFFSET | ||
} else { | ||
c | ||
} | ||
} | ||
|
||
fn is_lowercase(c: u8) -> bool { | ||
// This comparison is valid because the type of the value in the short | ||
// string format gets automatically inferred by the compiler | ||
c >= 'a' && c <= 'z' | ||
} | ||
|
||
fn is_whitespace(chr: u8) -> bool { | ||
chr == ' ' || chr == '\t' || chr == '\n' || chr == '\r' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[package] | ||
name = "welcome_to_tech_palace" | ||
version = "0.1.0" | ||
edition = "2024_07" | ||
|
||
[dev-dependencies] | ||
cairo_test = "2.9.2" |
Oops, something went wrong.