Add exercise 212, 258, fix clippy warnings
This commit is contained in:
parent
c5aa3d4abf
commit
6ff23340af
9
e_212/Cargo.toml
Normal file
9
e_212/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "e_212"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Emelie Graven <emelie@graven.dev>"]
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
130
e_212/src/main.rs
Normal file
130
e_212/src/main.rs
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
/*! # Description
|
||||||
|
|
||||||
|
When we Swedes are young, we are taught a SUPER-SECRET language that only kids know, so we can hide secrets from our confused parents. This language is known as "Rövarspråket" (which means "Robber's language", more or less), and is surprisingly easy to become fluent in, at least when you're a kid. Recently, the cheeky residents of /r/Sweden decided to play a trick on the rest on reddit, and get a thread entirely in Rövarspråket to /r/all. [The results were hilarious](http://np.reddit.com/r/sweden/comments/301sqr/dodetot_%C3%A4ror_fof%C3%B6ror_lolitote/).
|
||||||
|
|
||||||
|
Rövarspråket is not very complicated: you take an ordinary word and replace the consonants with the consonant doubled and with an "o" in between. So the consonant "b" is replaced by "bob", "r" is replaced with "ror", "s" is replaced with "sos", and so on. Vowels are left intact. It's made for Swedish, but it works just as well in English.
|
||||||
|
|
||||||
|
Your task today is to write a program that can encode a string of text into Rövarspråket.
|
||||||
|
|
||||||
|
(note: this is a higly guarded Swedish state secret, so I trust that none of you will share this very privileged information with anyone! If you do, you will be extradited to Sweden and be forced to eat [surströmming](http://en.wikipedia.org/wiki/Surstr%C3%B6mming) as penance.)
|
||||||
|
|
||||||
|
(note 2: surströmming is actually not that bad, it's much tastier than its reputation would suggest! I'd go so far as to say that it's the tastiest half-rotten fish in the world!)
|
||||||
|
|
||||||
|
# Formal inputs & outputs
|
||||||
|
## Input
|
||||||
|
|
||||||
|
You will recieve one line of input, which is a text string that should be encoded into Rövarspråket.
|
||||||
|
|
||||||
|
## Output
|
||||||
|
|
||||||
|
The output will be the encoded string.
|
||||||
|
|
||||||
|
A few notes: your program should be able to handle case properly, which means that "Hello" should be encoded to "Hohelollolo", and *not* as "HoHelollolo" (note the second capital "H").
|
||||||
|
|
||||||
|
Also, since Rövarspråket is a Swedish invention, your program should follow Swedish rules regarding what is a vowel and what is a consonant. The Swedish alphabet is the same as the English alphabet except that there are three extra characters at the end (Å, Ä and Ö) which are all vowels. In addition, Y is always a vowel in Swedish, so the full list of vowels in Swedish is A, E, I, O, U, Y, Å, Ä and Ö. The rest are consonants.
|
||||||
|
|
||||||
|
Lastly, any character that is not a vowel or a consonant (i.e. things like punctuation) should be left intact in the output.
|
||||||
|
|
||||||
|
# Example inputs
|
||||||
|
## Input 1
|
||||||
|
|
||||||
|
Jag talar Rövarspråket!
|
||||||
|
|
||||||
|
## Output 1
|
||||||
|
|
||||||
|
Jojagog totalolaror Rorövovarorsospoproråkoketot!
|
||||||
|
|
||||||
|
## Input 2
|
||||||
|
|
||||||
|
I'm speaking Robber's language!
|
||||||
|
|
||||||
|
## Output 2
|
||||||
|
|
||||||
|
I'mom sospopeakokinongog Rorobobboberor'sos lolanongoguagoge!
|
||||||
|
|
||||||
|
# Challenge inputs
|
||||||
|
|
||||||
|
## Input 1
|
||||||
|
|
||||||
|
Tre Kronor är världens bästa ishockeylag.
|
||||||
|
|
||||||
|
## Input 2
|
||||||
|
|
||||||
|
Vår kung är coolare än er kung.
|
||||||
|
|
||||||
|
# Bonus
|
||||||
|
|
||||||
|
Make your program able to decode a Rövarspråket-encoded sentence as well as encode it.
|
||||||
|
|
||||||
|
# Notes
|
||||||
|
|
||||||
|
This excellent problem (which filled my crusty old Swedish heart with glee) was suggested by /u/pogotc. Thanks so much for the suggestion!
|
||||||
|
|
||||||
|
If you have an idea for a problem, head on over to /r/dailyprogrammer_ideas and post your suggestion! If it's good idea, we might use it, and you'll be as cool as /u/pogotc.
|
||||||
|
*/
|
||||||
|
#![allow(dead_code)]
|
||||||
|
#![allow(unused)]
|
||||||
|
const CONSONANTS: [char; 40] = [
|
||||||
|
'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'w', 'v', 'x',
|
||||||
|
'z', 'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'W', 'V',
|
||||||
|
'X', 'Z',
|
||||||
|
];
|
||||||
|
fn main() {}
|
||||||
|
|
||||||
|
fn encode(input: String) -> String {
|
||||||
|
input.chars().fold(String::new(), |output, ch| {
|
||||||
|
if is_consonant(&ch) {
|
||||||
|
output + &ch.to_string() + "o" + &ch.to_string().to_ascii_lowercase()
|
||||||
|
} else {
|
||||||
|
output + &ch.to_string()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode(input: String) -> String {
|
||||||
|
let mut chars = input.chars();
|
||||||
|
let mut output = String::new();
|
||||||
|
while let Some(ch) = &chars.next() {
|
||||||
|
if is_consonant(ch) {
|
||||||
|
// Would use advance_by() here, but it requires nightly
|
||||||
|
chars.next();
|
||||||
|
chars.next();
|
||||||
|
}
|
||||||
|
output += &ch.to_string();
|
||||||
|
}
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_consonant(ch: &char) -> bool {
|
||||||
|
CONSONANTS.contains(ch)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn challenge_input_1() {
|
||||||
|
assert_eq!(encode(String::from("Tre Kronor är världens bästa ishockeylag.")), String::from("Totrore Kokrorononoror äror vovärorloldodenonsos bobäsostota isoshohocockokeylolagog."));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn challenge_input_2() {
|
||||||
|
assert_eq!(
|
||||||
|
encode(String::from("Vår kung är coolare än er kung.")),
|
||||||
|
String::from("Vovåror kokunongog äror cocoololarore änon eror kokunongog.")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bonus_challenge_input_1() {
|
||||||
|
assert_eq!(decode(String::from("Totrore Kokrorononoror äror vovärorloldodenonsos bobäsostota isoshohocockokeylolagog.")), (String::from("Tre Kronor är världens bästa ishockeylag.")));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn bonus_challenge_input_2() {
|
||||||
|
assert_eq!(
|
||||||
|
decode(String::from(
|
||||||
|
"Vovåror kokunongog äror cocoololarore änon eror kokunongog."
|
||||||
|
)),
|
||||||
|
String::from("Vår kung är coolare än er kung.")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
9
e_258/Cargo.toml
Normal file
9
e_258/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "e_258"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Emelie Graven <emelie@graven.dev>"]
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
106
e_258/src/main.rs
Normal file
106
e_258/src/main.rs
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/*!]]
|
||||||
|
# Description
|
||||||
|
|
||||||
|
A [network socket](https://en.wikipedia.org/wiki/Network_socket) is an endpoint of a connection across a computer network.
|
||||||
|
Today, most communication between computers is based on the Internet Protocol; therefore most network sockets are Internet
|
||||||
|
sockets. [Internet Relay Chat](https://simple.wikipedia.org/wiki/Internet_Relay_Chat) (IRC) is a chat system on the Internet.
|
||||||
|
It allows people from around the world to have conversations together, but it can also be used for two people to chat
|
||||||
|
privately.
|
||||||
|
|
||||||
|
[Freenode](https://en.wikipedia.org/wiki/Freenode) is an IRC network used to discuss peer-directed projects. Their servers
|
||||||
|
are all accessible from the domain names chat.freenode.net and irc.freenode.net. In 2010, it became the largest free and
|
||||||
|
open source software-focused IRC network. In 2013 it became the largest IRC network, encompassing more than 90,000 users
|
||||||
|
and 40,000 channels and gaining almost 5,000 new users per year. We have a channel on freenode ourselves for all things
|
||||||
|
/r/DailyProgrammer on freenode, which is
|
||||||
|
[#reddit-dailyprogrammer](https://www.reddit.com/r/dailyprogrammer/comments/2dtqr7/psa_rdailyprogrammer_irc_channel/).
|
||||||
|
|
||||||
|
Your challenge today will be to communicate with the freenode IRC server. This will consist of opening a TCP socket to
|
||||||
|
freenode and sending two protocol messages to initiate the connection. The original
|
||||||
|
[IRC RFC](https://tools.ietf.org/html/rfc1459#section-4.1) defines a message as a line of text up to 512 bytes starting
|
||||||
|
with a message code, followed by one or more space separated parameters, and ending with a CRLF (`\r\n`). The last
|
||||||
|
paramater can be prefixed by a colon to mark it as a parameter that can contain spaces, which will take up the rest of the
|
||||||
|
line. An example of a colon-prefixed parameter would be the contents of a chat message, as that is something that contains spaces.
|
||||||
|
|
||||||
|
The first of the two initiation messages (`NICK`) defines what name people will see when you send a chat message.
|
||||||
|
It will have to be unique, and you will not be able to connect if you specify a name which is currently in use or reserved.
|
||||||
|
It has a single parameter `<nickname>` and will be sent in the following form:
|
||||||
|
|
||||||
|
NICK <nickname>
|
||||||
|
|
||||||
|
The second of the two initiation messages (`USER`) defines your username, user mode, server name, and real name. The username must also be unique and is usually set to be the same as the nickname. Originally, hostname was sent instead of user mode, but this was changed in a later version of the IRC protocol. For our purposes, standard mode `0` will work fine. As for server name, this will be ignored by the server and is conventionally set as an asterisk (`*`). The real name parameter can be whatever you want, though it is usually set to be the same value as the nickname. It does not have to be unique and may contain spaces. As such, it must be prefixed by a colon. The `USER` message will be sent in the following form:
|
||||||
|
|
||||||
|
USER <username> 0 * :<realname>
|
||||||
|
|
||||||
|
# Input Description
|
||||||
|
|
||||||
|
You will give your program a list of lines specifying server, port, nickname, username, and realname. The first line will contain the server and the port, separated by a colon. The second through fourth lines will contain nick information.
|
||||||
|
|
||||||
|
chat.freenode.net:6667
|
||||||
|
Nickname
|
||||||
|
Username
|
||||||
|
Real Name
|
||||||
|
|
||||||
|
# Output Description
|
||||||
|
|
||||||
|
Your program will open a socket to the specified server and port, and send the two required messages. For example:
|
||||||
|
|
||||||
|
NICK Nickname
|
||||||
|
USER Username 0 * :Real Name
|
||||||
|
|
||||||
|
Afterwards, it will begin to receive messages back from the server. Many messages sent from the server will be prefixed to indicate the origin of the message. This will be in the format `:server` or `:nick[!user][@host]`, followed by a space. The exact contents of these initial messages are usually not important, but you must output them in some manner. The first few messages received on a successful connection will look something like this:
|
||||||
|
|
||||||
|
:wolfe.freenode.net NOTICE * :*** Looking up your hostname...
|
||||||
|
:wolfe.freenode.net NOTICE * :*** Checking Ident
|
||||||
|
:wolfe.freenode.net NOTICE * :*** Found your hostname
|
||||||
|
:wolfe.freenode.net NOTICE * :*** No Ident response
|
||||||
|
:wolfe.freenode.net 001 Nickname :Welcome to the freenode Internet Relay Chat Network Nickname
|
||||||
|
|
||||||
|
# Challenge Input
|
||||||
|
|
||||||
|
The server will occasionally send `PING` messages to you. These have a single parameter beginning with a colon. The exact contents of that parameter will vary between servers, but is usually a unique string used to verify that your client is still connected and responsive. On freenode, it appears to be the name of the specific server you are connected to. For example:
|
||||||
|
|
||||||
|
PING :wolfe.freenode.net
|
||||||
|
|
||||||
|
# Challenge Output
|
||||||
|
|
||||||
|
In response, you must send a `PONG` message with the parameter being the same unique string from the `PING`. You must continue to do this for the entire time your program is running, or it will get automatically disconnected from the server. For example:
|
||||||
|
|
||||||
|
PONG :wolfe.freenode.net
|
||||||
|
|
||||||
|
# Notes
|
||||||
|
|
||||||
|
You can see the full original IRC specification at https://tools.ietf.org/html/rfc1459. Sections 2.3 and 4.1 are of particular note, as they describe the message format and the initial connection. See also, http://ircdocs.horse/specs/.
|
||||||
|
|
||||||
|
[A Regular Expression For IRC Messages](https://mybuddymichael.com/writings/a-regular-expression-for-irc-messages.html)
|
||||||
|
|
||||||
|
Happy Pi Day!
|
||||||
|
*/
|
||||||
|
|
||||||
|
use std::error::Error;
|
||||||
|
use std::io::{BufRead, BufReader, Write};
|
||||||
|
use std::net::TcpStream;
|
||||||
|
|
||||||
|
const SERVER: &str = "irc.libera.chat:6667";
|
||||||
|
const NICK: &str = "dailyprog_2851";
|
||||||
|
const USER_NAME: &str = "dailyprog_2851";
|
||||||
|
const REAL_NAME: &str = "dailyprog_2851";
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut stream = TcpStream::connect(SERVER)?;
|
||||||
|
stream.write_all((String::from("NICK ") + NICK + "\r\n").as_bytes())?;
|
||||||
|
stream.write_all(
|
||||||
|
(String::from("USER ") + USER_NAME + " 0 * :" + REAL_NAME + "\r\n").as_bytes(),
|
||||||
|
)?;
|
||||||
|
let mut reader = BufReader::new(stream);
|
||||||
|
let mut line = String::new();
|
||||||
|
loop {
|
||||||
|
reader.read_line(&mut line)?;
|
||||||
|
println!("{}", &line);
|
||||||
|
if line.starts_with("PING") {
|
||||||
|
reader
|
||||||
|
.get_mut()
|
||||||
|
.write_all(line.replace("PING", "PONG").as_bytes())?;
|
||||||
|
}
|
||||||
|
line.clear();
|
||||||
|
}
|
||||||
|
}
|
|
@ -116,7 +116,7 @@ impl FromStr for Dice {
|
||||||
fn from_str(s: &str) -> Result<Dice, Self::Err> {
|
fn from_str(s: &str) -> Result<Dice, Self::Err> {
|
||||||
// Split string at "d" delimeter, parse elements into Dice struct containing u32s
|
// Split string at "d" delimeter, parse elements into Dice struct containing u32s
|
||||||
let dice = s
|
let dice = s
|
||||||
.split("d")
|
.split('d')
|
||||||
.map(|x| x.parse::<u32>())
|
.map(|x| x.parse::<u32>())
|
||||||
.collect::<Result<Vec<u32>, ParseIntError>>();
|
.collect::<Result<Vec<u32>, ParseIntError>>();
|
||||||
let dice = match dice {
|
let dice = match dice {
|
||||||
|
@ -149,7 +149,7 @@ fn main() {
|
||||||
/// Main exercise loop
|
/// Main exercise loop
|
||||||
fn e_364() {
|
fn e_364() {
|
||||||
let input = fs::read_to_string("input.txt").unwrap();
|
let input = fs::read_to_string("input.txt").unwrap();
|
||||||
let dice: Result<Vec<Dice>, DiceError> = input.split("\n").map(|x| x.parse()).collect();
|
let dice: Result<Vec<Dice>, DiceError> = input.split('\n').map(|x| x.parse()).collect();
|
||||||
match dice {
|
match dice {
|
||||||
Ok(d) => d.iter().for_each(|x| println!("{}", x.roll_dice())),
|
Ok(d) => d.iter().for_each(|x| println!("{}", x.roll_dice())),
|
||||||
Err(DiceError::ParseInt(e)) => eprintln!("Could not parse integer: {:?}", e),
|
Err(DiceError::ParseInt(e)) => eprintln!("Could not parse integer: {:?}", e),
|
||||||
|
@ -169,7 +169,7 @@ mod tests {
|
||||||
Dice { count: 16, die: 2 }
|
Dice { count: 16, die: 2 }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
#[test]
|
||||||
fn test_error_handling() {
|
fn test_error_handling() {
|
||||||
assert!(matches!("3dx".parse::<Dice>(), Err(DiceError::ParseInt(_))));
|
assert!(matches!("3dx".parse::<Dice>(), Err(DiceError::ParseInt(_))));
|
||||||
assert_eq!("3d3d3".parse::<Dice>(), Err(DiceError::ParseFields));
|
assert_eq!("3d3d3".parse::<Dice>(), Err(DiceError::ParseFields));
|
||||||
|
|
|
@ -98,6 +98,8 @@ Here's the first pass through the algorithm using the original example:
|
||||||
|
|
||||||
At this point you would start over at step 1 with the sequence `[5, 4, 4, 2, 1, 1, 1]`. After your second pass through the algorithm, your sequence will be `[3, 3, 1, 0, 0, 1]`, so start back at step 1 with this sequence. After your third pass you'll have `[2, 0, 0]`. On your fourth pass, you'll stop at step 5, because you'll have `N = 2` and an empty sequence (`[]`), and 2 > 0, so you will return false.
|
At this point you would start over at step 1 with the sequence `[5, 4, 4, 2, 1, 1, 1]`. After your second pass through the algorithm, your sequence will be `[3, 3, 1, 0, 0, 1]`, so start back at step 1 with this sequence. After your third pass you'll have `[2, 0, 0]`. On your fourth pass, you'll stop at step 5, because you'll have `N = 2` and an empty sequence (`[]`), and 2 > 0, so you will return false.
|
||||||
*/
|
*/
|
||||||
|
#![allow(dead_code)]
|
||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
|
@ -122,7 +124,7 @@ fn warmup_4(i: i32, mut set: Vec<i32>) -> Vec<i32> {
|
||||||
fn e_378(mut set: Vec<i32>) -> bool {
|
fn e_378(mut set: Vec<i32>) -> bool {
|
||||||
loop {
|
loop {
|
||||||
set = warmup_1(set);
|
set = warmup_1(set);
|
||||||
if set.len() == 0 {
|
if set.is_empty() {
|
||||||
break true;
|
break true;
|
||||||
}
|
}
|
||||||
set = warmup_2(set);
|
set = warmup_2(set);
|
||||||
|
|
Loading…
Reference in a new issue