Day 6: Tuning Trouble · Issue #8 · simonw/advent-of-code-2022-in-rust (original) (raw)

@simonw

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

@simonw

Correct answer for part 1: 1623

simonw added a commit that referenced this issue

Dec 6, 2022

@simonw

@simonw

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(())
}

@simonw

I'm going to learn rustfmt.

Not much to learn:

rustfmt day_06/src/main.rs

simonw added a commit that referenced this issue

Dec 6, 2022

@simonw

@simonw

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 call skip(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 call take(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 first i - 3 characters of the chars string, and take(4) is used to only take the next four characters, so that only the last four characters of the string are printed.

@simonw

@simonw

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

@simonw

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.

@simonw

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

@simonw

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

Dec 6, 2022

@simonw

@simonw

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(())
}

@simonw

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?

@simonw

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.

@simonw

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

Dec 6, 2022

@simonw

simonw added a commit that referenced this issue

Dec 6, 2022

@simonw

@simonw

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(())
}

@jabley