mirror of
https://github.com/javalsai/aoc.git
synced 2026-01-12 17:10:00 +01:00
do I hate my life? idek
This commit is contained in:
15
2024/04/p1/build.sh
Executable file
15
2024/04/p1/build.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euxo pipefail
|
||||
|
||||
rustup run nightly rustc \
|
||||
--target x86_64-unknown-none \
|
||||
-Crelocation-model=static \
|
||||
\
|
||||
-Copt-level=3 \
|
||||
-Ctarget-cpu=native \
|
||||
-Cpanic=abort \
|
||||
-Cstrip=symbols \
|
||||
-Coverflow_checks=n \
|
||||
-Clto \
|
||||
\
|
||||
$* -o main main.rs
|
||||
@@ -1,30 +1,255 @@
|
||||
use std::{
|
||||
cmp,
|
||||
fs::File,
|
||||
io::Read,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(naked_functions)]
|
||||
#![allow(static_mut_refs)]
|
||||
|
||||
fn main() -> std::io::Result<()> {
|
||||
let args: Vec<_> = std::env::args().collect();
|
||||
let filename = &args[1];
|
||||
let runs: u32 = args[2]
|
||||
use core::{
|
||||
arch::{asm, naked_asm},
|
||||
cmp,
|
||||
ffi::CStr,
|
||||
fmt::{self, Debug, Write},
|
||||
mem, ops,
|
||||
panic::PanicInfo,
|
||||
usize,
|
||||
};
|
||||
// use std::{fs::File, io::Read};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct CInstant {
|
||||
secs: i64, // time_t
|
||||
nanos: i64, // long
|
||||
}
|
||||
|
||||
impl CInstant {
|
||||
fn now() -> Self {
|
||||
let clockid: isize = 1; // CLOCK_MONOTONIC (non-jumping-backwards uptime)
|
||||
let instant = unsafe {
|
||||
let mut instant: Self = mem::zeroed();
|
||||
let mut result: isize;
|
||||
|
||||
asm!(
|
||||
"syscall",
|
||||
in("rax") 228,
|
||||
in("rsi") &mut instant,
|
||||
in("rdi") clockid,
|
||||
lateout("rax") result,
|
||||
out("rcx") _,
|
||||
out("r11") _,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
if result < 0 {
|
||||
Err(result)
|
||||
} else {
|
||||
Ok(instant)
|
||||
}
|
||||
};
|
||||
|
||||
instant.expect("cant even trust syscalls on stack nowadays")
|
||||
}
|
||||
|
||||
pub fn as_nanos(self) -> i128 {
|
||||
(self.secs as i128) * 1_000_000_000 + (self.nanos as i128)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Sub for CInstant {
|
||||
type Output = CDuration;
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
CDuration::from(self.as_nanos() - rhs.as_nanos())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct CDuration {
|
||||
pub nanos: i128,
|
||||
}
|
||||
|
||||
const IS_SUB_UNITS: &[char] = &['n', 'μ', 'm'];
|
||||
impl Debug for CDuration {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut i = 0;
|
||||
let max_idx = 3;
|
||||
let mut amount = self.nanos;
|
||||
|
||||
while amount >= 1000 && i < max_idx {
|
||||
amount /= 1000;
|
||||
i += 1;
|
||||
}
|
||||
|
||||
write!(f, "{amount}")?;
|
||||
if i != 3 {
|
||||
write!(f, "{}", IS_SUB_UNITS[i])?;
|
||||
}
|
||||
|
||||
write!(f, "s")
|
||||
}
|
||||
}
|
||||
|
||||
impl CDuration {
|
||||
pub const ZERO: CDuration = CDuration::from(0);
|
||||
pub const MAX: CDuration = CDuration::from(i128::MAX);
|
||||
|
||||
pub const fn from(nanos: i128) -> Self {
|
||||
Self { nanos }
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::DivAssign<u32> for CDuration {
|
||||
fn div_assign(&mut self, rhs: u32) {
|
||||
self.nanos /= rhs as i128
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Div<u32> for CDuration {
|
||||
type Output = CDuration;
|
||||
fn div(mut self, rhs: u32) -> Self::Output {
|
||||
self /= rhs;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::AddAssign for CDuration {
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
self.nanos += rhs.nanos;
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Neg for CDuration {
|
||||
type Output = Self;
|
||||
fn neg(mut self) -> Self::Output {
|
||||
self.nanos = -self.nanos;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
// FD
|
||||
struct FDWriter(usize);
|
||||
|
||||
impl FDWriter {
|
||||
pub const fn from_fd(fd: usize) -> Self {
|
||||
Self(fd)
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for FDWriter {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
unsafe {
|
||||
let result: isize;
|
||||
asm!(
|
||||
"syscall",
|
||||
in("rax") 1, // write
|
||||
in("rdi") self.0, // fd
|
||||
in("rsi") s.as_ptr() as *const u8, // *data
|
||||
in("rdx") s.as_bytes().len(), // data len
|
||||
lateout("rax") result,
|
||||
out("rcx") _,
|
||||
out("r11") _,
|
||||
options(nostack)
|
||||
);
|
||||
|
||||
if result < 0 {
|
||||
Err(fmt::Error)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[naked]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn _start() {
|
||||
unsafe {
|
||||
naked_asm!(
|
||||
"mov {0}, rsp",
|
||||
"jmp {1}",
|
||||
sym STACK_START,
|
||||
sym main
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static mut ARGC: usize = 1;
|
||||
static mut STACK_START: *const () = unsafe { mem::zeroed() };
|
||||
fn get_arg(idx: usize) -> Option<&'static CStr> {
|
||||
unsafe {
|
||||
if idx >= ARGC {
|
||||
return None;
|
||||
}
|
||||
|
||||
let ptr = ((STACK_START as usize) + (idx * 8) + 8) as *const *const i8;
|
||||
let cstr = core::ffi::CStr::from_ptr(*ptr);
|
||||
Some(cstr)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exit(code: isize) -> ! {
|
||||
unsafe {
|
||||
asm!(
|
||||
"syscall",
|
||||
in("rax") 60,
|
||||
in("rdi") code,
|
||||
options(nostack, noreturn)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static mut STDOUT: FDWriter = FDWriter::from_fd(1);
|
||||
static mut STDERR: FDWriter = FDWriter::from_fd(2);
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
unsafe {
|
||||
_ = writeln!(&mut STDERR, "\x1b[1;31m{info:?}\x1b[0m");
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pub fn unsafe_sized_slice_collect<T, I: Iterator<Item = T>>(slice: &mut [T], iter: I) -> usize {
|
||||
let mut i = 0;
|
||||
for e in iter {
|
||||
slice[i] = e;
|
||||
i += 1;
|
||||
}
|
||||
i
|
||||
}
|
||||
|
||||
pub extern "C" fn main() -> ! {
|
||||
unsafe {
|
||||
ARGC = *(STACK_START as *const usize);
|
||||
}
|
||||
|
||||
// let args: Vec<_> = std::env::args().collect();
|
||||
// let filename = &args[1];
|
||||
let runs: u32 = get_arg(1)
|
||||
.expect("no arg 1")
|
||||
.to_str()
|
||||
.expect("invalid string encoding")
|
||||
.parse()
|
||||
.expect("did not receive a number as `runs` argument");
|
||||
|
||||
let mut contents = vec![];
|
||||
let mut file = File::open(filename)?;
|
||||
file.read_to_end(&mut contents)?;
|
||||
let lines: Vec<_> = contents.split(|&b| b == b'\n').collect();
|
||||
// let mut contents = vec![];
|
||||
// let mut file = File::open(filename)?;
|
||||
// file.read_to_end(&mut contents)?;
|
||||
let contents: &[u8] = include_bytes!("../input.txt");
|
||||
|
||||
let mut max = Duration::ZERO;
|
||||
let mut avg = Duration::ZERO;
|
||||
let mut min = Duration::MAX;
|
||||
let result = run(&lines);
|
||||
let mut lines: [&[u8]; 1024] = [&[]; 1024];
|
||||
let len = unsafe_sized_slice_collect(&mut lines, contents.split(|&b| b == b'\n'));
|
||||
|
||||
let mut max = CDuration::ZERO;
|
||||
let mut avg = CDuration::ZERO;
|
||||
let mut min = CDuration::MAX;
|
||||
_ = writeln!(
|
||||
unsafe { &mut STDOUT },
|
||||
"\x1b[0;1;31;43m[W]\x1b[0;1;33m syscall time {:?}\x1b[0m",
|
||||
-(CInstant::now() - CInstant::now())
|
||||
);
|
||||
let result = run(&lines, len);
|
||||
for i in 0..runs {
|
||||
let a = Instant::now();
|
||||
let run_result = run(&lines);
|
||||
let b = Instant::now();
|
||||
let a = CInstant::now();
|
||||
let run_result = run(&lines, len);
|
||||
let b = CInstant::now();
|
||||
if result != run_result {
|
||||
panic!(
|
||||
"supposed result is {} but this run got {} after {} runs",
|
||||
@@ -38,13 +263,15 @@ fn main() -> std::io::Result<()> {
|
||||
avg += d / runs;
|
||||
}
|
||||
|
||||
println!("\x1b[0;34mtotal \x1b[1;33m{result}\x1b[0;34m\n runs \x1b[1;33m{runs:?}\x1b[0;34m\n avg. \x1b[1;35m{avg:?}\x1b[0;34m\n max. \x1b[1;31m{max:?}\x1b[0;34m\n min. \x1b[1;32m{min:?}\x1b[0m");
|
||||
Ok(())
|
||||
_ = writeln!(unsafe { &mut STDOUT }, "\x1b[0;34mtotal \x1b[1;33m{result}\x1b[0;34m\n runs \x1b[1;33m{runs:?}\x1b[0;34m\n avg. \x1b[1;35m{avg:?}\x1b[0;34m\n max. \x1b[1;31m{max:?}\x1b[0;34m\n min. \x1b[1;32m{min:?}\x1b[0m");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
fn run(lines: &[&[u8]]) -> usize {
|
||||
fn run(lines: &[&[u8]], len: usize) -> usize {
|
||||
let mut t = 0;
|
||||
for (i, ln) in lines.iter().enumerate() {
|
||||
for i in 0..len {
|
||||
let ln = lines[i];
|
||||
for (j, &ch) in ln.iter().enumerate() {
|
||||
if ch == b'X' {
|
||||
for dir in [
|
||||
|
||||
Reference in New Issue
Block a user