Day 6: Tuning Trouble · Issue #8 · simonw/advent-of-code-2022-in-rust (original) (raw)
Built this solution entirely using Copilot, no ChatGPT at all.
Tried it against the four examples:
day_06 % cargo run example1.txt
Finished dev [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/day_06 example1.txt`
wbjp
5
day_06 % cargo run example2.txt
Finished dev [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/day_06 example2.txt`
dvjt
6
day_06 % cargo run example3.txt
Finished dev [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/day_06 example3.txt`
fntj
10
day_06 % cargo run example4.txt
Finished dev [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/day_06 example4.txt`
qfrl
11
Correct answer for part 1: 1623
simonw added a commit that referenced this issue
use std::env; |
---|
use std::fs; |
use std::io; |
use std::io::BufRead; |
fn main() -> Result<(), std::io::Error> { |
let args: Vec<String> = env::args().collect(); |
if args.len() <= 1 { |
println!("error: missing required argument 'filename'"); |
return Ok(()); |
} |
let filename = &args[1]; |
// Read the first line of the file as a string |
let file = fs::File::open(filename)?; |
let reader = io::BufReader::new(file); |
let mut lines = reader.lines(); |
let line = lines.next().unwrap()?; |
// Turn that into a vector of chars |
let chars: Vec<char> = line.chars().collect(); |
for i in 4..chars.len() { |
// Put previous four characters in a set |
let mut set = std::collections::HashSet::new(); |
for j in i-4..i { |
set.insert(chars[j]); |
} |
// If the set has 4 characters, print last 4 |
if set.len() == 4 { |
println!("{}{}{}{}", chars[i-3], chars[i-2], chars[i-1], chars[i]); |
println!("{}", i); |
break; |
} |
} |
Ok(()) |
} |
I'm going to learn rustfmt
.
Not much to learn:
rustfmt day_06/src/main.rs
simonw added a commit that referenced this issue
I asked ChatGPT:
println!(
"{}{}{}{}",
chars[i - 3],
chars[i - 2],
chars[i - 1],
chars[i]
);
Show me more ways to do this
It gave me these two useful options:
for i in 0..4 { print!("{}", chars.get(i).unwrap()); }
And:
let four_chars = chars.chars().skip(i - 3).take(4); for c in four_chars { print!("{}", c); }
I said:
What do skip() and take() do?
It replied:
In Rust, the
skip()
method on an iterator allows you to skip a certain number of elements from the start of the iterator. For example, if you have an iterator that produces the numbers 1 to 10, and you callskip(3)
on it, the resulting iterator will produce the numbers 4 to 10.The
take()
method, on the other hand, allows you to only take a certain number of elements from the start of the iterator. So if you have the same iterator as before and you calltake(3)
on it, the resulting iterator will only produce the numbers 1 to 3.In the code you provided,
skip(i - 3)
is used to skip the firsti - 3
characters of thechars
string, andtake(4)
is used to only take the next four characters, so that only the last four characters of the string are printed.
day_06 % cargo add clap
Updating crates.io index
Adding clap v4.0.29 to dependencies.
Features:
+ color
+ error-context
+ help
+ std
+ suggestions
+ usage
- cargo
- debug
- deprecated
- derive
- env
- string
- unicode
- unstable-doc
- unstable-grouped
- unstable-replace
- unstable-v5
- wrap_help
The code ChatGPT gave me yesterday fails:
error[E0432]: unresolved import `clap::App`
--> src/main.rs:1:12
|
1 | use clap::{App, Arg};
| ^^^ no `App` in the root
I think it gave me example code for a much older version of the library.
I'm going to use the example from the docs https://docs.rs/clap/latest/clap/ instead.
I had to run cargo add clap --features derive
to get that to work.
I think this is what I want:
use clap::Parser;
#[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] struct Args { /// File to read filename: String,
/// Length of characters to seek #[arg(short, long, default_value_t = 4)] length: u8, }
fn main() -> Result<(), std::io::Error> { let args = Args::parse(); println!("{} {}", args.filename, args.length); Ok(()) }
Help output:
day_06 % cargo run -- --help
Compiling day_06 v0.1.0 (/Users/simon/Dropbox/Development/advent-of-code-2022-in-rust/day_06)
Finished dev [unoptimized + debuginfo] target(s) in 2.19s
Running `target/debug/day_06 --help`
Usage: day_06 [OPTIONS] <FILENAME>
Arguments:
<FILENAME> File to read
Options:
-l, --length <LENGTH> Length of characters to seek [default: 4]
-h, --help Print help information
-V, --version Print version information
Weird, my new code works against the example:
day_06 % cargo run example-2-1.txt --length 14
Compiling day_06 v0.1.0 (/Users/simon/Dropbox/Development/advent-of-code-2022-in-rust/day_06)
Finished dev [unoptimized + debuginfo] target(s) in 1.89s
Running `target/debug/day_06 example-2-1.txt --length 14`
Found it
mgbljsphdztnvj
Index: 19
day_06 % cargo run input.txt --length 14
Finished dev [unoptimized + debuginfo] target(s) in 0.11s
Running `target/debug/day_06 input.txt --length 14`
But fails to return a result for the input.txt
file:
day_06 % cargo run input.txt --length 14
Finished dev [unoptimized + debuginfo] target(s) in 0.15s
Running `target/debug/day_06 input.txt --length 14`
day_06 %
simonw added a commit that referenced this issue
use clap::Parser; |
---|
use std::fs; |
use std::io; |
use std::io::BufRead; |
#[derive(Parser, Debug)] |
#[command(author, version, about, long_about = None)] |
struct Args { |
/// File to read |
filename: String, |
/// Length of characters to seek |
#[arg(short, long, default_value_t = 4)] |
length: u8, |
} |
fn main() -> Result<(), std::io::Error> { |
let args = Args::parse(); |
let length = args.length; |
// Read the first line of the file as a string |
let file = fs::File::open(args.filename)?; |
let reader = io::BufReader::new(file); |
let mut lines = reader.lines(); |
let line = lines.next().unwrap()?; |
// Turn that into a vector of chars |
let chars: Vec<char> = line.chars().collect(); |
for i in args.length..(chars.len() as u8) { |
// Put previous X characters in a set |
let mut set = std::collections::HashSet::new(); |
for j in i - args.length..i { |
set.insert(chars[j as usize]); |
} |
// If the set has X characters, print last X |
if set.len() == args.length.into() { |
println!("Found it"); |
let x_chars = chars.iter().skip((i - (length - 1)).into()).take(length.into()); |
println!("{}", x_chars.collect::<String>()); |
println!("Index: {}", i); |
break; |
} |
} |
Ok(()) |
} |
It's passing on all the examples, but it's failing on input.txt
for BOTH exercises now.
So maybe there's something that goes wrong with the length of the file?
Asked ChatGPT:
Maximum value of a rust u8
It said:
The maximum value of a rust
u8
is 255.u8
is an unsigned 8-bit integer, which means it can hold values from 0 to 2^8-1 (or 0 to 255 in decimal). This is the largest value that can be stored in a single byte of memory.
I bet that's what's going wrong here.
Yes, that was the problem:
day_06 % cargo run input.txt --length 14
Compiling day_06 v0.1.0 (/Users/simon/Dropbox/Development/advent-of-code-2022-in-rust/day_06)
Finished dev [unoptimized + debuginfo] target(s) in 2.11s
Running `target/debug/day_06 input.txt --length 14`
Found it
fmzdwnpvbjrshm
Index: 3774
simonw added a commit that referenced this issue
simonw added a commit that referenced this issue
use clap::Parser; |
---|
use std::fs; |
use std::io; |
use std::io::BufRead; |
#[derive(Parser, Debug)] |
#[command(author, version, about, long_about = None)] |
struct Args { |
/// File to read |
filename: String, |
/// Length of characters to seek |
#[arg(short, long, default_value_t = 4)] |
length: u16, |
} |
fn main() -> Result<(), std::io::Error> { |
let args = Args::parse(); |
let length = args.length; |
// Read the first line of the file as a string |
let file = fs::File::open(args.filename)?; |
let reader = io::BufReader::new(file); |
let mut lines = reader.lines(); |
let line = lines.next().unwrap()?; |
// Turn that into a vector of chars |
let chars: Vec<char> = line.chars().collect(); |
for i in args.length..(chars.len() as u16) { |
// Put previous X characters in a set |
let mut set = std::collections::HashSet::new(); |
for j in i - args.length..i { |
set.insert(chars[j as usize]); |
} |
// If the set has X characters, print last X |
if set.len() == args.length.into() { |
println!("Found it"); |
let x_chars = chars |
.iter() |
.skip((i - (length - 1)).into()) |
.take(length.into()); |
println!("{}", x_chars.collect::<String>()); |
println!("Index: {}", i); |
break; |
} |
} |
Ok(()) |
} |