main.s
.global _start
.section .text
_start:
movq (%rsp), %rax
cmp $1, %rax
jle _args_fail
#open
movq $2, %rax #open
movq 16(%rsp), %rdi #fname
xor %rsi, %rsi #flags 0 is rdonly
xor %rsi, %rsi #mode used when creating a new file
syscall
//store fd in r15
movq %rax, %r15
#fstat for size
movq $5, %rax #fstat
movq %r15, %rdi #fd
leaq .statbuf(%rip), %rsi #statbuf
syscall
#mmap
movq $9, %rax
xor %rdi, %rdi # addr(?)
movq .statbuf+48(%rip), %rsi #length
movq $7, %rdx # read/write/exec permissions
movq $2, %r10 # map_private will not change underlying file
movq %r15, %r8 #fd
movq $0, %r9
syscall
movq %rax, %r14
movq %rax, %r13 #addr of end
addq .statbuf+48(%rip), %r13
sub $3, %r13 #only continue if there are 3 more chars in the file
movq $0, %r15 #total score
movq $0, %rax
movq $0, %rbx
_start_of_round:
movb (%r14), %al
subb $64, %al # 'A' - 64 = 1
add %rax, %r15 # add score
add $2, %r14 # goto op move
movb (%r14), %bl
subb $87, %bl
subb %al, %bl
cmp $0, %bl
je _draw
cmp $1, %bl
je _lose
cmp $-2, %bl
je _lose
#subq
_win:
add $3, %r15
_draw:
add $3, %r15
_lose:
add $2, %r14
cmp %r14, %r13
jg _start_of_round
leaq .printfmt(%rip), %rdi
movq %r15, %rsi
call printf@PLT
movq $60, %rax
movq $0, %rdi
syscall
_args_fail:
leaq .args_fail_msg(%rip), %rdi
call puts@PLT
movq $60, %rax
movq $1, %rdi
syscall
.section .data
.args_fail_msg:
.asciz "file name must be provided"
.printfmt:
.asciz "%d\n"
.section .bss
.lcomm .statbuf 144
main.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<fcntl.h>
int main(int argc, char** argv){
if(argc < 2){
printf("you must provide a filename\n");
return 1;
}
int fd = open(argv[1], O_RDONLY, 0);
struct stat* statbuf = (struct stat*) malloc(sizeof(struct stat));
fstat(fd,statbuf);
char* filebuf = (char*) mmap(0,statbuf->st_size + 1,PROT_READ | PROT_WRITE,MAP_PRIVATE,fd,0);
filebuf[statbuf->st_size] = 0; //for debug
int total_score = 0;
char* fbuf_end = filebuf + statbuf->st_size;
while(filebuf + 4 <= fbuf_end){
int my_move = filebuf[0] - 64;
total_score+=my_move;
int opp_move = filebuf[2] - 87;
int s = opp_move-my_move;
if(s == 0)
total_score+=3;
if(s == -1 || s == 2)
total_score+=6;
filebuf+=4; //"A B\n"
}
printf("%d", total_score);
free(statbuf);
munmap(filebuf,statbuf->st_size+1);
}
main.rs
use std::fs;
use std::env;
fn main(){
let f_cont = fs::read_to_string(env::args().nth(1).unwrap()).expect("no file");
let mut total_score: u64 = 0;
for line in f_cont.split("\n"){
let s = line.as_bytes();
if s.len() < 3 { continue; }
let my_move = s[0] - 64;
total_score+=my_move as u64;
let op_move = s[2] - 87;
let result: i16 = op_move as i16 - my_move as i16;
if result == 0 {
total_score+=3;
}
if result == -1 || result == 2 {
total_score+=6;
}
}
println!("{}", total_score);
}
main.py
#!/usr/bin/env python3
import sys
match = {
"A X": 3, "A Y": 0, "A Z": 6,
"B X": 6, "B Y": 3, "B Z": 0,
"C X": 0, "C Y": 6, "C Z": 3
}
base={
"A": 1, "B": 2, "C": 3
}
if(len(sys.argv) < 2):
print("you must provide an agument")
exit()
lines = [i for i in open(sys.argv[1]).read().split("\n") if i in match]
total_score = 0
for line in lines:
total_score+=match[line] + base[line[0:1]]
print(total_score)
main.rb
#!/usr/bin/ruby
match = {
"A X" => 3, "A Y" => 0, "A Z" => 6,
"B X" => 6, "B Y" => 3, "B Z" => 0,
"C X" => 0, "C Y" => 6, "C Z" => 3
}
base ={
"A" => 1, "B" => 2, "C" => 3
}
total_score = 0
File.foreach(ARGV[0]) { |line|
if not match.key?(line.chomp)
next
end
total_score+= base[line[0,1]] + match[line.chomp]
}
puts total_score
main.hs
import Data.Map
import System.Environment
import System.IO
matchMap = Data.Map.fromList([
("A X", 3), ("A Y", 0), ("A Z", 6),
("B X", 6), ("B Y", 3), ("B Z", 0),
("C X", 0), ("C Y", 6), ("C Z", 3)])
moveMap = Data.Map.fromList([("A", 1), ("B", 2), ("C", 3)])
main = do
args <- getArgs
handle <- openFile(args !! 0) ReadMode
contents <- hGetContents handle
print $ totalScore $ lines contents
hClose handle
totalScore :: [String] -> Int
totalScore x = sum $ Prelude.map roundScore x
roundScore :: String -> Int
roundScore s = if length s /= 0
then findWithDefault 0 [(s !! 0)] moveMap + findWithDefault 0 s matchMap
else 0
times.txt
time it took for each program to run on a ~400mb file 100M lines
main.s: 0.832s
main.c: 1.587s
main.rs: 13.177s
main.py: 40.642s
main.rb: 1m43.046s
main.hs: 2m6.875s (used 22GB of ram)