main.s
.global _start
.section .text
_start:
movq (%rsp), %rax
cmp $1, %rax
jle _args_fail
movq $2, %rax #open
xor %rsi, %rsi #flags 0 is readonly
xor %rsi, %rsi #mode only used when creating files
movq 16(%rsp), %rdi #args[1]
syscall
movq %rax, %r15 #fd
movq $5, %rax #fstat
movq %r15, %rdi
leaq .statbuf(%rip), %rsi
syscall
movq $9, %rax #mmap to map file to memory
xor %rdi, %rdi #addr, not used here
movq .statbuf+48(%rip), %rsi #length of the allocation (size of file)
movq $7, %rdx #permissions read/write/exec
movq $2, %r10 #map_private (don't save changes to the file)
movq %r15, %r8 #fd
movq $0, %r9 #offset
syscall
mov %rax, %r15 #current point in alloc
sub $1, %r15
mov %rax, %r14
add .statbuf+48(%rip), %r14 #enf of alloc
mov $0, %rax #clear the register
movq $0, %r10 # the total score
_start_of_comp1:
inc %r15
call _get_line_length
movq %rax, %rdx
shr $1, %rdx
call _clear_sackbuf
leaq .rucksackbuf-1(%rip), %rsi
_start_of_char1:
cmp %r15, %r14 #if(eof)
je _end
movb (%r15), %al
movb %al, %r9b
dec %rdx
inc %r15
call _get_priority
movq %rsi, %rdi #load suckbuf-1 addr
add %rax, %rdi # get to the correct index
movb $'A, (%rdi) # set to present
cmp $0, %rdx
je _start_of_comp2
jmp _start_of_char1
_start_of_comp2:
cmp %r15, %r14
je _end
movb (%r15), %al
cmp $'\n, %al
je _start_of_comp1
inc %r15
call _get_priority
movq %rsi, %rdi
add %rax, %rdi
cmpb $0, (%rdi)
je _start_of_comp2
_found_match:
add %rax, %r10
cmp %r15, %r14
je _end
_goto_line_end:
movb (%r15), %al
cmp $'\n, %al
je _start_of_comp1
inc %r15
jmp _goto_line_end
_end:
movq %r10, %rsi
leaq .printfmt(%rip), %rdi
call printf@PLT
movq $60, %rax
movq $0, %rdi
syscall
_get_line_length:
movq %r15, %rdi
movq $0, %rax
_loop_start:
cmp %rdi, %r14
je _loop_end
movb (%rdi), %sil
cmp $'\n, %sil
je _loop_end
inc %rax
inc %rdi
jmp _loop_start
_loop_end:
ret
_get_priority: #replace the value in %al with the priority of the item
sub $38, %al #correct priority for capital letters
cmp $53, %al
jge _lowercase
ret
_lowercase:
sub $58, %al
ret
_clear_sackbuf:
#push %rax
#push %rsi
#push %rdi
movq $0, .rucksackbuf(%rip)
movq $0, .rucksackbuf+8(%rip)
movq $0, .rucksackbuf+16(%rip)
movq $0, .rucksackbuf+24(%rip)
movq $0, .rucksackbuf+32(%rip)
movq $0, .rucksackbuf+40(%rip)
movl $0, .rucksackbuf+48(%rip)
#pop %rdi
#pop %rsi
#pop $rax
ret
_args_fail:
leaq .args_fail_message(%rip), %rdi
call puts@PLT
movq $60, %rax
movq $1, %rdi
syscall
.section .data
.args_fail_message:
.asciz "you must provide a filename"
.printfmt:
.asciz "%d\n"
.section .bss
.lcomm .statbuf 144
.lcomm .rucksackbuf 52
main.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
int getpri(char c){
c -= 38;
if(c > 52)
c-=58;
return c;
}
int main(int argc, char** argv) {
if(argc != 2){
fprintf(stderr, "you must give filename plz");
return 1;
}
FILE* fp = fopen(argv[1], "r");
int total_score = 0;
char* line;
size_t line_len;
char primap[52];
int ln=0;
while(1) {
memset(primap,0,52);
if(getline(&line,&line_len,fp) == -1)
break;
ln++;
if(line==NULL)
break;
if(*line=='\n')
break;
if(*line==0)
break;
line_len = strlen(line);
if(line_len %2 == 1){
line_len--;
line[line_len]=0;
}
for(int i=0;i<line_len/2;i++)
primap[getpri(line[i])-1] = 1;
for(int i=line_len/2;i<line_len;i++) {
if (primap[getpri(line[i])-1]){
total_score+=getpri(line[i]);
goto eol;
}
}
eol:
if(line)
free(line);
line=0;
}
printf("%d\b", total_score);
}
main.py
#!/usr/bin/env python3
import sys
import re
lines = open(sys.argv[1]).read().split("\n")
total_score = 0
for line in lines[0:-1]:
first_half = line[:len(line)//2]
second_half = line[len(line)//2:]
doublechar = list(set(first_half) & set(second_half))[0]
pri = ord(doublechar) - 38
if pri > 52:
pri -= 58
total_score+=pri
print(total_score)
main.rs
use std::fs;
use std::env;
fn get_intersection (first: &[u8], second: &[u8]) -> u8{
for i in first{
for j in second {
if *i == *j{
return *i;
}
}
}
return 0;
}
fn main(){
let f_cont = fs::read_to_string(env::args().nth(1).unwrap()).expect("no file");
let f_cont = f_cont.split("\n");
let mut total_score:u64 =0;
for line in f_cont{
if line.len() == 0 {
continue;
}
let line = line.as_bytes();
let (first, second) = line.split_at(line.len()/2);
let doublechar = get_intersection(first,second);
if doublechar < 91{
total_score += doublechar as u64 - 38;
} else{
total_score += doublechar as u64 - 96;
}
}
println!("{}",total_score);
}
main.rb
#!/usr/bin/ruby
def get_priority(x)
if x.ord < 91
return x.ord - 38
else
return x.ord - 96
end
end
total_score = 0
File.foreach(ARGV[0]) { |line|
line=line.chars
spl = line.each_slice(line.size / 2).to_a
spl = spl[0] & spl[1]
total_score+=get_priority spl[0]
}
puts total_score
main.hs
import System.IO
import System.Environment
import Data.Char (ord)
main = do
args <- getArgs
handle <- openFile(args !! 0) ReadMode
contents <- hGetContents handle
let half_lists = map halfList $ lines contents
print $ sum $ map getPriority $ map intersect half_lists
getLineScore :: String -> Int
getLineScore s = 5
halfList :: [a] -> ([a],[a])
halfList x = splitAt(length x `div` 2) x
intersect :: Eq a => ([a], [a]) -> a
intersect (l1, l2) = (filter (\n -> n `elem` l1) l2) !! 0
getPriority :: Char -> Int
getPriority x =
if ord x < 91 then ord x - 38
else ord x - 96
times.txt
time it took each program to run on a ~500mb file, 5 million lines
main.s: 2.235s line length: O(n) number of lines: O(n)
main.c: 4.410s line length: O(n) number of lines: O(n)
main.py: 22.920s line length: O(n) number of lines: O(n)
main.rs: 49.507s line length: O(n^2) number of lines: O(n)
main.rb: 1m58.724s line length: O(n^2) number of lines: O(n)
main.hs: 2m11.189 i don't know, but it used 22 gb of ram