From c079e80137ae5d11411223f6b10ce12835372f34 Mon Sep 17 00:00:00 2001 From: "matthias@arch" Date: Mon, 5 Dec 2022 14:24:14 +0100 Subject: [PATCH] day 4 --- 3/README.md | 7 + 3/day3-1.vim | 47 ++ 4/.gitignore | 3 + 4/.vimspector.json | 22 + 4/Makefile | 14 + 4/README.md | 28 ++ 4/day4-from-ai.c | 71 +++ 4/day4-from-ai.s | 66 +++ 4/day4.s | 294 +++++++++++++ 4/prompt.md | 26 ++ 4/section-pairs.txt | 1000 +++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 1578 insertions(+) create mode 100644 3/day3-1.vim create mode 100644 4/.gitignore create mode 100644 4/.vimspector.json create mode 100644 4/Makefile create mode 100644 4/README.md create mode 100644 4/day4-from-ai.c create mode 100644 4/day4-from-ai.s create mode 100644 4/day4.s create mode 100644 4/prompt.md create mode 100644 4/section-pairs.txt diff --git a/3/README.md b/3/README.md index 9314c95..bde3750 100644 --- a/3/README.md +++ b/3/README.md @@ -3,9 +3,16 @@ Today's language: **C** +Extra: Task 1 in **vimscript**, generated by OpenAI with just a few fixes by myself + All the characters (the Elf's items) occuring in (half) a line (backpack) are stored as bits in an unsigned long, duplicate characters can then be determined by bitwise and-ing these numbers. ```shell # Find the item type that appears in both compartments of each rucksack. What is the sum of the priorities of those item types? gcc main.c -o day3 ./day3 + +# OpenAI vim script +vim rucksack_items.txt +# in vim: +# :source day3-1.vim ``` diff --git a/3/day3-1.vim b/3/day3-1.vim new file mode 100644 index 0000000..0aa72ea --- /dev/null +++ b/3/day3-1.vim @@ -0,0 +1,47 @@ +" Define the function that will be run when the script is executed +function! FindAndSumCharacters() + " Initialize the sum to 0 + let sum = 0 + + " Iterate over every line in the file + " Note: The cursor position is not relevant here, since the script + " will process the entire file + for line in getline(1, '$') + " Get the first and second half of the line + let first_half = line[:len(line)/2] + let second_half = line[len(line)/2:] + + " Find the character that occurs in both the first and second half + " of the line. + " Note: There will be only one such character, since the prompt + " specified that each line contains only a-zA-Z + let common_char = '' + for char in first_half + if match(second_half, '\C' . char) >= 0 + let common_char = char + " echo first_half . " - " . second_half . " - char" . common_char + break + endif + endfor + + " Convert the character to a number + let common_char_num = char2nr(common_char) + let char_num = 0 + if common_char_num >= char2nr('a') && common_char_num <= char2nr('z') + let char_num = common_char_num - char2nr('a') + 1 + elseif common_char_num >= char2nr('A') && common_char_num <= char2nr('Z') + let char_num = common_char_num + 27 - char2nr('A') + endif + " echo "char_num " . char_num . "for char " . common_char . " char2nr " . char2nr(common_char) + + " Add the number to the sum + let sum += char_num + endfor + + " Output the final sum + echo sum +endfunction + +" Run the script when it is loaded +call FindAndSumCharacters() + diff --git a/4/.gitignore b/4/.gitignore new file mode 100644 index 0000000..95fdab6 --- /dev/null +++ b/4/.gitignore @@ -0,0 +1,3 @@ +*.o +.old +day4 diff --git a/4/.vimspector.json b/4/.vimspector.json new file mode 100644 index 0000000..a7a9ea2 --- /dev/null +++ b/4/.vimspector.json @@ -0,0 +1,22 @@ +{ + "configurations": { + "vulkan_test": { + "adapter": "vscode-cpptools", + "configuration": { + "name": "day4", + "type": "asmdbg", + "request": "launch", + "externalConsole": true, + "logging": { + "engineLogging": true + }, + "stopOnEntry": true, + "stopAtEntry": true, + "debugOptions": [], + "MIMode": "gdb", + "cwd": "~/Sonstiges/AdventOfCode/4", + "program": "~/Sonstiges/AdventOfCode/4/day4" + } + } + } +} diff --git a/4/Makefile b/4/Makefile new file mode 100644 index 0000000..7e235b6 --- /dev/null +++ b/4/Makefile @@ -0,0 +1,14 @@ +ASM_SRC = day4.s +C_SRC = day4-from-ai.c +# DEBUG = -g +DEBUG = + +asm: + as -o day4.o $(ASM_SRC) $(DEBUG) + ld $(DEBUG) -o day4 day4.o -lc + @# for some reason an invalid interpreter is in the binary, which leads to 'file not found error' when running + patchelf --set-interpreter "/usr/lib/ld-linux-x86-64.so.2" day4 + +c: + gcc $(C_SRC) -o day4 "section-pairs.txt" + diff --git a/4/README.md b/4/README.md new file mode 100644 index 0000000..3fc1a55 --- /dev/null +++ b/4/README.md @@ -0,0 +1,28 @@ +# [Day 4](https://adventofcode.com/2022/day/4) +:gift::gift::gift::gift: +Today's language: **gnu x86-64** (and alternatively **c**) + +Today I wanted to use OpenAI to solve the tasks using gnu x86-64, which I have never used before +(I did some small things in [6502-asssembly](https://github.com/MatthiasQuintern/6502), so it wasn't all new). +The prompt can be seen in prompt.txt. +It did a lot of things right, however: +- It did generate x86 (32-bit) code because I did not specify x86-64. So I changed the `int $0x80` system calls to use `syscall` (which also meant I had to change all the registers and [syscall numbers](https://filippo.io/linux-syscall-table/)) +- It did get the argument order for `sscanf` wrong, even when I specifically asked it told me that the line to read comes last +- It did not correctly implement the logic to test the condition +- It sometimes me wrong syscall numbers (they were just wrong, not even x86) +- It told me the `read` syscall can read until a `newline` by passing `newline` as last arg + +So I had to fix all that. I tried to exclusively use the AI to get answers to my questions, however I did sometimes revert to the internet. +It was still a good starting point and provided lots of help. +At the end of the ~~evening~~ next morning I had coded the task in x86-64 assembly. + +To test scanf, I gave it the exact same prompt but said I wanted it in *c*. +It instantly produced compilable c code that gave the right answer... +```shell +# for the assembly program +make asm +./day4 +# for the c promgram +make c +./day4 +``` diff --git a/4/day4-from-ai.c b/4/day4-from-ai.c new file mode 100644 index 0000000..dbfd76b --- /dev/null +++ b/4/day4-from-ai.c @@ -0,0 +1,71 @@ +#include +#include +#include + +/* + * This file was generated by OpenAI and was not modified apart from this comment. The prompt was: + * consider a text file like this: + * 22-65,22-66 + * 91-94,63-91 + * 6-88,5-31 + * 85-86,64-86 + * 40-65,40-65 + * 25-82,24-94 + * + * write c program that: + * - reads a text file like this line by line and count how often one of the two ranges contains the other. + * - accepts the filename via command line arg + * - outputs the result using printf with a suitable string + * A range r1 contains the other r2 when the r1.lower <= r2.lower and r1.upper >= r2.upper + * the program needs to output how often that is the case in the entire file + */ + +// Structure to represent a range in the file +struct range { + int lower; + int upper; +}; + +// Function to parse a line from the file and return the two ranges in the line +void parse_line(const char *line, struct range *range1, struct range *range2) { + // Parse the two ranges in the line + sscanf(line, "%d-%d,%d-%d", &range1->lower, &range1->upper, &range2->lower, &range2->upper); +} + +int main(int argc, char *argv[]) { + // Check if a filename was provided + if (argc < 2) { + fprintf(stderr, "Error: No filename provided\n"); + return 1; + } + + // Open the file for reading + FILE *fp = fopen(argv[1], "r"); + if (fp == NULL) { + fprintf(stderr, "Error: Unable to open file for reading\n"); + return 1; + } + + // Read the file line by line + char line[256]; + int count = 0; + while (fgets(line, sizeof(line), fp) != NULL) { + // Parse the two ranges in the line + struct range range1, range2; + parse_line(line, &range1, &range2); + + // Check if one range contains the other + if ((range1.lower <= range2.lower && range1.upper >= range2.upper) || + (range2.lower <= range1.lower && range2.upper >= range1.upper)) { + count++; + } + } + + // Close the file + fclose(fp); + + // Print the result + printf("The file contains %d lines where one of the two ranges contains the other\n", count); + + return 0; +} diff --git a/4/day4-from-ai.s b/4/day4-from-ai.s new file mode 100644 index 0000000..6e649bd --- /dev/null +++ b/4/day4-from-ai.s @@ -0,0 +1,66 @@ + .data +filename: .asciz "input.txt" +format: .asciz "%d-%d,%d-%d" +result: .asciz "Result: %d\n" + + .text + .globl main + +main: + pushl %ebp + movl %esp, %ebp + + xorl %eax, %eax # initialize count to 0 + movl $1, %ebx # initialize loop variable to 1 + + # open the file and store the file descriptor in %ecx + movl $5, %eax # set the number of the "open" syscall to 5 + movl $filename, %ebx # move the address of the filename to %ebx + xorl %edx, %edx # set the flags to 0 + int $0x80 + + # read the file line by line + .loop: + movl $3, %eax # set the number of the "read" syscall to 3 + movl %ecx, %ebx # move the file descriptor to %ebx + movl $buffer, %ecx # move the address of the buffer to %ecx + movl $BUFSIZ, %edx # move the size of the buffer to %edx + int $0x80 + + # check if end of file has been reached + cmpl $0, %eax + jz .done # if so, jump to .done + + # parse the line and check if it satisfies the condition + call sscanf + movl %eax, %edi + movl %ebx, %esi + movl %ecx, %ebp + movl %edx, %ebx + cmpl %edi, %ebp + jl .not_contained + cmpl %esi, %ebx + jg .not_contained + incl %eax # increment count + + .not_contained: + incl %ebx # increment loop variable + + jmp .loop # repeat the loop + + .done: + # print the result + movl $1, %eax # set the number of the "write" syscall to 1 + movl $1, %ebx # set the file descriptor to stdout (1) + movl $result, %ecx # move the address of the result string to %ecx + movl %eax, %edx # move the count to %edx + int $0x80 + + # close the file + movl $6, %eax # set the number of the "close" syscall to 6 + movl %ecx, %ebx # move the file descriptor to %ebx + int $0x80 + + leave + ret + diff --git a/4/day4.s b/4/day4.s new file mode 100644 index 0000000..3a57635 --- /dev/null +++ b/4/day4.s @@ -0,0 +1,294 @@ +# Parts of this code were generated by OpenAI +# I did however have to modifiy nearly all of it + +.data + count_contained:.long 0 + count_overlap: .long 0 + file: .quad 0 # file descriptor + line_length: .quad 0 # store the length of the current line in line_buffer + line_nr: .long 0 # store the line number + r1_upper: .long 0 # range 1 upper value + r2_upper: .long 0 # range 2 upper value + r1_lower: .long 0 # range 1 lower value + r2_lower: .long 0 # range 2 lower value + current_char: .long 0 + + filename: .asciz "section-pairs.txt" + format: .asciz "%d-%d,%d-%d" + f_contained: .asciz "Current line has containment. count_contained: [%d]\n" + f_res_cont: .asciz "The file contains %d lines where one of the two ranges contains the other\n" + f_res_over: .asciz "The file contains %d lines where one of the two ranges overlaps the other\n" + f_line_nr: .asciz "Line Nr: [%d] -\t" + f_line_length: .asciz "Line Length: [%d] -\tContent: '" + f_q_newline: .asciz "'\n" + f_error_open: .asciz "Error %d while opening file\n" + f_error_read: .asciz "Error %d while reading file.\n" + f_error_match: .asciz "Error %d while matching line.\n" + +LINE_BUFSIZ = 32 +PRINT_BUFSIZ = 100 +SYS_READ = 0 +SYS_WRITE = 1 +SYS_OPEN = 2 +SYS_CLOSE = 3 +SYS_EXIT = 60 +STDOUT = 1 + +.bss + line_buffer: .skip LINE_BUFSIZ + print_buffer: .skip PRINT_BUFSIZ + +.text +.globl _start +.globl sscanfl + + +# syscall arg order +# (call #: rax) - rdi rsi rdx r10 r8 r9 +_start: + push %rbp + mov %rsp, %rbp + + # xorl %eax, %eax # initialize count_contained to 0 + # movl $1, %ebx # initialize loop variable to 1 + + # open the file and store the file descriptor in %ecx + movq $SYS_OPEN, %rax # set the number of the "open" syscall + movq $filename, %rdi # move the address of the filename to %ebx + xorq %rsi, %rsi # set the flags to 0 + xorq %rdx, %rdx # set the mode to 0 = read + # movq $777, %rsi + syscall + + # if read fails, jump to error + jl .error_open + jg .error_open + # negative return value is error + cmpq $0, %rax + jl .error_open + + movq %rax, file # store file descriptor in file + + # read the file line by line + .loop: + call read_next_line + + cmpq $0, %rax # rax is number of chars read, if 0 we are done + je .done + + # get and print line lenght + movq %rax, line_length + + # increment line nr + incl line_nr # increment line_nr + + # print line nr + movl line_nr, %edx # load to print + leaq f_line_nr, %rsi # set print format + push %rdx + call print_rsi_rdx + pop %rdx + + # print line lenght + movq line_length, %rdx + leaq f_line_length, %rsi + push %rdx + call print_rsi_rdx + pop %rdx + + # print the line + movq $SYS_WRITE, %rax # set the number of the "write" syscall to 4 + movq $STDOUT, %rdi # move the file descriptor (1 for stdout) to %ebx + movq $LINE_BUFSIZ, %rdx # number of bytes + leaq line_buffer, %rsi # buffer + syscall + + # print newline + movq $SYS_WRITE, %rax # set the number of the "write" syscall to 4 + movq $STDOUT, %rdi # move the file descriptor (1 for stdout) to %ebx + movq $2, %rdx # number of bytes + leaq f_q_newline, %rsi # buffer + syscall + + # from first arg to last + leaq line_buffer, %rdi # Load the address of the line_buffer into %rdi + leaq format, %rsi # Move the address of the format string into %rs + leaq r1_lower, %rdx # Move the address of the first output register into %esi + leaq r1_upper, %rcx # Move the address of the second output register into %edx + leaq r2_lower, %r8 # Move the address of the third output register into %ecx + leaq r2_upper, %r9 # Move the address of the fourth output register into %r8d + + push %rbx # to align the stack + call sscanf # Call the scanf function + pop %rbx # restore stack ptr + cmp $0, %rax + je .error_match # 0 is not succesful + + # load the results into registers + movl r1_lower, %eax + movl r2_lower, %ebx + movl r1_upper, %ecx + movl r2_upper, %edx + + cmp %ebx, %eax # compare r1l to r2l + jg .cont_r1l_greater_r2l + je .is_contained # if lower bounds are equal, one must be contained in the other + jl .cont_r1l_less_r2l + + # 1) check containment + .cont_r1l_greater_r2l: # r1l > r2l + # to be contained: r1u <= r2u + cmp %edx, %ecx + jl .is_contained + je .is_contained + jmp .not_contained + + + .cont_r1l_less_r2l: + # to be contained: r1u >= r1u + cmp %edx, %ecx + jg .is_contained + je .is_contained + jmp .not_contained + + movq $42, %rax + jmp .error_open # it should not come to this + + .is_contained: + incl count_contained + jmp .overlaps # containment € overlap + .not_contained: + + # 2) overlap + # two ranges overlap if + # r1l > r2l: + # r1l <= r2u + # r1l < r2l: + # r1u >= r2l + # r1l == r2l + cmpl %ebx, %eax # compare r1l to r2l + jg .over_r1l_greater_r2l + je .overlaps + jl .over_r1l_less_r2l + + movq $43, %rax + jmp .error_open # should not happen + + .over_r1l_greater_r2l: # r1l > r2l + cmpl %edx, %eax # overlap if r1l <= r2u + je .overlaps + jl .overlaps + jmp .no_overlap + + .over_r1l_less_r2l: # r1l < r2l + cmpl %ebx, %ecx # overlap if r1u >= r2l + jg .overlaps + je .overlaps + jmp .no_overlap + + .overlaps: + incl count_overlap + + .no_overlap: + + jmp .loop # repeat the loop + + .done: + + movl count_contained, %edx + leaq f_res_cont, %rsi # set print format + push %rsi + call print_rsi_rdx + pop %rsi + + movl count_overlap, %edx + leaq f_res_over, %rsi # set print format + push %rsi + call print_rsi_rdx + pop %rsi + + movq $0, %r10 # set exit status + jmp .close_file + + .error_open: + leaq f_error_open, %rsi # set print format + jmp .error + .error_read: + leaq f_error_read, %rsi # set print format + jmp .error + .error_match: + leaq f_error_match, %rsi # set print format + .error: + movq %rax, %rdx # print rax + # leaq f_error, %rsi # set print format + push %rax + call print_rsi_rdx + pop %rax + movq %rax, %r10 # set exit status + + .close_file: + # close the file, expect exit status in %r10 + movq $SYS_CLOSE, %rax # set the number of the "close" syscall to 3 + movq file, %rdi # move the file descriptor to %rdi + syscall + + leave + + movq $SYS_EXIT, %rax + movq %r10, %rdi + syscall + + +read_next_line: + # read char by char, until newline or eof, return number of chars in rax + xorq %r10, %r10 # charcount_contained + xorq %rsi, %rsi # make sure rsi is 0 + xorq %r11, %r11 # make sure r11 is 0 + .load_char: + movq $SYS_READ, %rax # set the number of the "read" syscall + movq file, %rdi # move the file descriptor to %rdi + leaq current_char, %rsi # move the address of the charbuffer to %rsi + movq $1, %rdx # read only 1 char + syscall + + jl .error_read + + cmpq $0, %rax # if no char is loaded - eof + je .line_complete + + movb current_char, %r11b + + cmpb $'\n', %r11b # if newline + je .line_complete + + movb %r11b, line_buffer(,%r10,1) # copy current char into the place at charcount_contained + incq %r10 # increment charcount_contained + jmp .load_char + .line_complete: + # null terminate the line + leaq line_buffer, %rax + movq $0, (%rax,%r10,1) + + movq %r10, %rax # return number of chars loaded in rax + ret + +print_rsi_rdx: + # print an int with $format, first get the formatted string from sprintf and the do a write syscall to stdout + # print the format string in %rsi which contains one int in %rdx + push %rdx # save the value + + # Set up the format string and the integer value + leaq print_buffer, %rdi # Load the address of the buffer into %rdi + # Use sprintf to format the string and the integer value + call sprintf # Call the sprintf function + # Determine the number of bytes written to the buffer + movq %rax, %rdx # Move the number of bytes written to %rdx + + # Set up the write syscall + movq $SYS_WRITE, %rax # set the number of the "write" syscall to 4 + movq $STDOUT, %rdi # move the file descriptor (1 for stdout) to %ebx + leaq print_buffer, %rsi + syscall + + pop %rdx + ret diff --git a/4/prompt.md b/4/prompt.md new file mode 100644 index 0000000..90d7c50 --- /dev/null +++ b/4/prompt.md @@ -0,0 +1,26 @@ +# original prompt +consider a text file like this: +22-65,22-66 +91-94,63-91 +6-88,5-31 +85-86,64-86 +40-65,40-65 +25-82,24-94 + +write an gnu-x86 assembly program that: +- reads a text file like this line by line and count how often one of the two ranges contains the other. +- accepts the filename via command line arg +- outputs the result using printf with a suitable string +A range r1 contains the other r2 when the r1.lower <= r2.lower and r1.upper >= r2.upper +the program needs to output how often that is the case in the entire file + +# add task 2 to c code: +can you add another check to the c code: +it should now also check if one of the ranges overlaps the other. +A range r1 overlaps the other r2 if: +- r1.lower == r2.lower +- r1.upper == r2.upper +- r1.lower > r2.lower and r1.lower <= r2.upper +- r1.upper < r1.upper r1.upper >= r2.lower +... +sorry i failed to mention that the overlaps and containment should be counted separately diff --git a/4/section-pairs.txt b/4/section-pairs.txt new file mode 100644 index 0000000..3b72ab6 --- /dev/null +++ b/4/section-pairs.txt @@ -0,0 +1,1000 @@ +22-65,22-66 +91-94,63-91 +6-88,5-31 +85-86,64-86 +40-65,40-65 +25-82,24-94 +68-69,68-92 +60-91,89-92 +3-72,3-73 +44-85,84-85 +15-72,14-72 +84-92,84-92 +10-84,3-10 +32-62,31-61 +14-98,98-99 +24-78,24-61 +2-5,5-89 +58-95,58-59 +39-93,92-93 +11-82,81-82 +12-37,13-58 +53-92,52-91 +1-19,3-18 +90-91,91-98 +20-72,19-71 +91-91,1-92 +71-90,71-93 +77-94,77-94 +48-76,48-76 +48-58,48-53 +3-42,2-14 +3-4,3-94 +4-9,7-8 +14-97,77-97 +66-66,17-65 +12-99,13-98 +29-74,30-74 +30-93,29-92 +43-44,42-46 +7-9,8-81 +21-77,1-89 +85-92,86-91 +56-72,73-73 +16-75,17-42 +2-85,1-85 +97-97,13-98 +3-94,3-33 +55-91,1-99 +14-21,14-15 +1-3,2-98 +43-57,43-56 +9-95,8-10 +18-80,81-92 +19-72,19-71 +17-94,62-86 +45-59,46-60 +73-88,46-87 +63-82,82-86 +63-88,87-98 +20-28,20-56 +76-76,70-75 +36-73,35-73 +85-91,85-90 +4-82,4-85 +2-2,1-98 +27-71,27-81 +13-79,13-14 +32-43,33-42 +53-97,98-99 +41-62,42-66 +23-78,23-77 +6-92,6-91 +1-86,1-85 +3-89,84-90 +5-79,78-80 +51-73,50-72 +48-81,49-82 +32-33,33-88 +4-97,4-97 +13-88,14-65 +33-74,32-75 +26-48,48-78 +1-46,16-33 +2-6,6-67 +5-93,5-93 +5-6,4-22 +68-83,38-84 +10-70,18-69 +10-77,70-76 +4-94,3-93 +22-95,21-99 +32-72,31-92 +30-75,29-74 +3-96,95-95 +96-96,61-81 +52-77,53-77 +1-2,1-94 +4-96,3-98 +29-58,30-56 +31-49,30-60 +33-79,27-80 +10-51,8-11 +8-36,8-36 +36-93,36-92 +9-60,10-15 +48-80,79-87 +39-41,40-49 +48-87,64-87 +30-34,2-57 +81-82,13-81 +3-15,15-99 +37-72,38-72 +10-85,5-84 +6-79,78-93 +75-80,76-84 +55-72,55-55 +8-66,9-9 +54-64,63-99 +6-77,7-48 +2-64,1-32 +31-91,90-90 +19-66,18-94 +58-75,26-76 +58-60,1-59 +90-90,87-91 +5-91,5-91 +67-67,3-66 +13-81,31-36 +31-61,23-60 +18-92,17-91 +85-86,15-86 +10-68,9-11 +52-85,12-84 +7-27,26-26 +43-50,21-50 +25-75,74-75 +7-7,6-24 +1-63,42-62 +11-12,11-66 +25-94,93-93 +13-48,31-47 +3-58,59-59 +1-54,1-1 +5-5,5-96 +59-70,7-71 +18-19,18-81 +9-96,10-84 +33-41,33-38 +1-99,1-98 +69-83,68-78 +19-82,8-81 +2-23,3-24 +57-90,57-98 +75-83,74-76 +68-68,16-69 +2-86,1-33 +5-92,6-14 +51-76,52-75 +25-72,24-46 +9-76,10-50 +5-51,23-52 +19-83,20-93 +33-69,44-70 +22-69,23-69 +55-61,40-62 +2-16,16-81 +66-98,66-96 +27-85,28-86 +43-93,88-94 +19-83,32-82 +2-92,26-52 +87-87,45-93 +40-81,97-99 +4-97,98-98 +19-95,6-20 +52-96,53-53 +2-34,2-97 +62-83,63-66 +9-74,8-81 +53-83,53-83 +35-73,11-72 +9-97,10-95 +9-51,10-50 +25-27,26-35 +45-60,45-46 +12-65,28-65 +40-92,40-91 +5-5,4-98 +72-91,90-91 +16-87,17-91 +97-97,18-96 +77-78,75-79 +22-48,32-47 +70-70,35-69 +45-98,99-99 +65-83,83-92 +2-95,4-88 +5-10,10-46 +4-84,50-85 +58-58,15-59 +11-80,3-22 +46-48,3-47 +29-80,30-30 +34-96,5-95 +65-97,32-96 +26-31,30-46 +12-12,12-77 +26-92,26-92 +29-92,29-90 +26-27,27-30 +4-30,3-29 +29-57,1-28 +99-99,42-97 +92-97,78-98 +3-90,46-91 +44-76,43-75 +24-28,10-25 +1-95,1-52 +3-3,3-61 +39-94,40-93 +41-86,75-94 +28-28,26-27 +21-94,21-97 +12-41,41-54 +4-49,3-5 +75-90,44-75 +4-83,78-82 +5-93,93-94 +33-90,89-90 +12-32,13-98 +41-99,98-99 +4-67,3-38 +95-95,11-95 +7-46,7-46 +11-18,18-24 +7-92,12-57 +60-91,90-91 +86-94,86-95 +11-58,57-57 +7-10,10-97 +1-46,3-46 +1-52,1-2 +16-94,74-93 +7-98,18-97 +8-76,8-74 +37-92,54-91 +63-86,88-96 +4-55,47-58 +70-92,91-95 +73-77,71-77 +3-99,5-99 +56-58,56-57 +53-73,13-74 +88-97,97-97 +52-63,51-60 +13-94,14-91 +2-93,3-99 +42-75,67-75 +38-39,38-88 +8-93,92-97 +13-32,17-31 +3-17,16-53 +1-1,3-95 +5-88,4-87 +76-89,47-77 +5-54,4-55 +45-95,90-96 +81-89,36-88 +31-36,32-60 +87-99,10-88 +17-89,47-88 +26-94,25-99 +43-90,42-43 +59-87,59-80 +34-43,37-41 +1-54,1-53 +2-91,2-3 +40-95,46-95 +8-14,14-55 +38-52,51-69 +16-62,15-63 +30-55,31-74 +46-59,10-74 +35-81,80-88 +10-86,10-98 +18-68,18-68 +5-50,5-92 +48-98,99-99 +6-71,4-72 +6-6,6-43 +27-39,26-36 +15-15,14-82 +91-98,29-92 +46-51,50-52 +5-99,5-98 +4-91,4-92 +82-83,81-85 +68-78,21-68 +32-70,69-93 +25-59,25-60 +40-52,40-40 +28-68,93-94 +13-99,50-98 +10-33,10-11 +11-46,8-11 +20-32,19-31 +9-63,3-62 +24-92,92-97 +57-68,68-69 +39-91,39-91 +57-97,49-83 +2-58,21-92 +14-99,15-98 +42-90,43-51 +51-51,20-51 +29-43,39-43 +8-91,7-99 +11-75,11-76 +33-98,34-97 +99-99,28-97 +35-82,11-35 +80-82,45-81 +52-56,53-55 +29-77,28-93 +6-95,1-94 +12-77,12-13 +28-90,27-29 +71-74,72-77 +4-97,4-97 +40-85,39-60 +36-38,25-38 +25-35,24-28 +20-57,51-54 +80-81,3-81 +18-98,97-98 +82-94,71-83 +5-95,6-87 +16-78,3-79 +3-74,4-75 +14-87,13-42 +93-93,8-94 +7-20,9-21 +6-76,6-7 +4-98,69-99 +67-95,94-94 +66-87,79-86 +45-94,45-46 +9-13,10-46 +71-84,8-83 +3-56,4-82 +35-89,36-61 +54-77,53-55 +46-95,46-94 +9-19,7-19 +18-19,19-42 +37-54,53-54 +14-91,14-90 +9-35,9-36 +20-20,20-45 +96-97,25-83 +11-55,10-10 +10-95,11-89 +30-34,30-86 +30-37,35-38 +70-71,53-71 +6-12,6-10 +4-34,34-95 +48-79,48-72 +5-99,6-6 +60-77,78-94 +64-64,13-63 +13-31,14-30 +7-23,8-24 +87-92,88-93 +34-81,35-74 +7-58,8-77 +3-98,3-99 +7-94,94-95 +3-12,2-88 +21-97,22-72 +13-77,95-97 +15-77,15-16 +67-82,68-83 +28-28,25-56 +51-52,33-52 +12-90,12-90 +24-72,25-99 +1-56,3-55 +40-84,39-84 +8-9,8-86 +31-71,31-72 +76-90,64-75 +19-90,91-91 +42-70,45-69 +51-93,80-92 +21-36,22-37 +96-99,97-97 +83-99,1-98 +40-43,34-61 +1-97,2-96 +1-92,1-91 +11-92,9-73 +57-57,56-66 +13-71,12-75 +70-89,70-71 +12-24,16-24 +10-35,56-63 +18-85,51-76 +20-46,1-45 +4-64,4-64 +48-52,48-50 +84-85,17-85 +48-64,63-64 +19-28,27-29 +4-16,3-17 +29-66,2-28 +8-88,55-70 +60-84,61-85 +8-69,8-69 +15-67,3-68 +42-95,96-99 +21-55,22-54 +64-70,19-71 +17-82,17-81 +4-80,3-81 +7-95,7-73 +12-34,4-33 +3-95,63-96 +1-96,93-94 +45-50,36-49 +63-89,45-64 +8-96,9-87 +93-93,1-92 +10-11,10-11 +2-6,6-99 +40-41,40-68 +4-91,3-90 +4-68,66-68 +37-84,36-85 +15-85,29-86 +77-79,53-78 +50-81,80-81 +51-66,50-72 +53-53,29-54 +42-78,5-77 +35-53,36-76 +17-17,18-18 +4-79,4-79 +23-38,23-38 +46-81,80-80 +26-93,25-37 +59-61,20-60 +82-96,82-94 +16-40,17-21 +5-95,5-98 +26-26,26-64 +32-40,32-75 +3-55,6-54 +28-86,28-86 +4-87,4-96 +4-88,24-99 +4-66,5-5 +9-61,8-89 +48-70,48-70 +36-37,14-37 +21-49,21-50 +57-62,14-35 +8-62,8-66 +14-96,11-97 +13-44,43-44 +12-87,11-86 +2-24,25-97 +3-83,2-98 +10-80,10-80 +4-94,2-4 +1-77,20-77 +28-79,17-79 +8-82,7-7 +6-87,77-82 +4-93,3-65 +94-94,38-95 +74-92,74-93 +13-68,12-69 +41-51,41-42 +22-93,21-23 +7-12,13-64 +58-87,51-88 +18-66,19-91 +1-70,71-71 +9-17,8-37 +3-32,4-97 +54-90,27-91 +1-94,3-93 +3-99,4-70 +16-92,16-91 +22-57,22-57 +4-78,31-53 +28-94,28-29 +19-48,16-18 +48-68,49-67 +23-39,22-24 +12-87,23-95 +36-47,37-46 +66-69,66-68 +35-94,36-93 +13-22,2-20 +41-53,52-54 +4-51,3-96 +52-52,5-53 +20-85,19-84 +4-78,3-79 +86-98,15-97 +68-85,68-87 +2-55,3-54 +27-63,11-64 +75-83,52-83 +18-75,19-74 +7-88,8-87 +1-86,1-92 +6-43,38-44 +71-71,70-71 +6-43,24-83 +15-53,15-63 +69-97,69-69 +9-99,12-13 +31-41,41-42 +11-53,10-57 +46-67,14-70 +24-35,25-36 +13-91,23-90 +62-67,68-70 +62-99,63-68 +10-84,51-85 +5-98,1-98 +16-97,81-98 +51-92,41-52 +15-88,14-93 +3-92,2-93 +44-74,44-74 +4-95,94-96 +51-62,25-63 +28-69,11-68 +3-82,3-78 +5-95,5-98 +25-96,25-99 +9-9,9-66 +17-18,1-18 +2-86,4-85 +4-9,9-92 +2-98,2-98 +61-96,60-98 +1-89,35-50 +89-89,25-90 +1-99,1-33 +53-73,52-74 +30-55,29-90 +97-98,70-91 +66-69,65-66 +31-83,82-83 +2-67,67-95 +77-78,77-96 +30-98,30-98 +94-94,28-95 +37-83,8-82 +14-46,28-30 +75-80,12-81 +19-68,18-19 +65-85,96-99 +62-63,3-63 +19-95,97-97 +54-79,55-78 +12-98,97-99 +83-98,41-84 +68-88,34-69 +25-25,20-25 +2-66,8-99 +84-85,21-85 +52-98,53-87 +32-55,31-54 +4-51,6-90 +46-86,47-47 +75-75,10-76 +30-38,29-49 +5-96,4-5 +49-49,49-93 +8-67,39-65 +6-51,5-70 +38-70,39-69 +2-98,2-3 +51-53,50-59 +56-92,57-91 +11-90,11-52 +19-99,20-98 +54-77,52-55 +6-93,1-6 +62-80,58-62 +27-82,26-97 +10-79,9-78 +18-99,18-99 +7-87,7-84 +44-44,45-86 +89-91,6-90 +15-98,15-95 +56-59,54-60 +61-89,2-82 +30-78,12-96 +10-84,1-10 +61-62,46-62 +5-74,5-6 +29-33,30-32 +81-95,95-99 +51-98,50-85 +6-79,49-78 +47-52,12-61 +4-58,3-89 +75-94,31-76 +43-49,42-44 +3-4,4-47 +44-98,98-98 +67-72,66-72 +2-38,3-38 +3-5,4-47 +5-95,5-95 +34-97,35-78 +66-68,67-98 +28-32,29-35 +44-68,31-44 +28-53,27-55 +16-73,17-67 +12-49,49-97 +34-76,75-75 +38-96,37-43 +15-20,20-79 +15-22,22-35 +3-25,4-55 +6-90,6-89 +17-74,18-75 +15-60,14-61 +6-29,29-81 +23-66,11-24 +37-90,90-90 +1-24,2-57 +42-78,41-79 +94-99,74-95 +95-97,2-30 +13-61,56-60 +23-82,24-83 +56-56,31-57 +58-91,57-99 +13-25,14-24 +46-54,47-77 +47-74,73-74 +23-48,22-82 +79-80,81-81 +16-33,6-76 +54-70,55-70 +44-67,45-66 +2-4,3-97 +24-94,19-94 +33-77,49-93 +13-35,35-73 +28-84,28-83 +6-89,7-90 +40-80,42-80 +39-84,65-83 +83-83,59-84 +20-46,30-46 +31-34,32-46 +12-13,13-67 +35-75,34-74 +20-20,20-89 +13-70,5-60 +25-25,24-24 +84-87,83-86 +26-58,26-58 +6-96,5-7 +4-78,5-79 +15-15,15-27 +7-79,3-80 +62-64,24-63 +68-69,32-71 +27-68,28-41 +43-43,11-44 +27-82,83-83 +54-70,26-69 +16-16,17-70 +27-34,33-35 +33-97,96-97 +4-5,4-39 +43-43,43-92 +27-33,1-28 +23-91,23-58 +9-51,8-10 +4-6,5-76 +5-34,33-95 +97-98,46-98 +20-53,52-65 +7-72,6-96 +32-79,93-95 +21-86,20-85 +47-82,46-84 +9-96,8-86 +10-93,11-75 +11-12,11-77 +7-56,6-55 +3-7,7-43 +54-84,55-55 +3-95,3-97 +18-55,37-56 +40-68,39-91 +56-87,56-85 +12-34,13-35 +7-62,8-63 +95-95,54-95 +7-94,6-94 +14-92,13-99 +18-42,42-53 +75-96,76-95 +5-78,4-6 +93-94,14-94 +25-91,25-92 +96-98,97-99 +82-84,82-85 +37-39,38-42 +11-48,7-49 +64-66,65-90 +10-46,9-45 +35-92,34-52 +6-94,9-93 +12-96,95-96 +16-86,63-67 +5-96,5-96 +54-59,19-60 +3-92,3-52 +26-54,27-53 +28-97,28-93 +98-98,83-97 +64-98,13-99 +79-84,80-86 +5-98,4-97 +2-23,22-35 +7-11,7-87 +31-94,32-59 +25-41,17-42 +28-94,76-95 +6-93,5-94 +73-94,74-93 +6-44,17-44 +2-99,22-46 +1-73,1-72 +25-71,25-72 +35-36,6-36 +6-66,5-66 +92-95,92-95 +53-75,52-75 +5-55,3-97 +12-76,43-75 +5-49,13-48 +32-32,8-37 +18-96,19-19 +17-59,17-60 +1-17,2-95 +37-82,83-83 +39-79,39-39 +25-81,25-86 +11-52,51-51 +91-91,30-91 +43-58,44-57 +1-98,2-98 +31-62,31-62 +6-13,6-13 +65-92,13-91 +3-6,5-95 +21-88,14-21 +48-75,47-74 +70-93,30-92 +37-58,58-89 +14-24,14-23 +31-60,58-83 +4-95,1-56 +47-79,98-98 +36-65,37-38 +6-18,19-75 +14-50,98-99 +44-94,45-93 +37-39,38-56 +39-57,38-40 +7-36,6-90 +81-83,28-82 +15-86,15-77 +70-86,2-44 +8-23,7-23 +28-31,29-78 +5-67,4-66 +31-31,14-32 +45-95,13-96 +11-39,40-40 +6-95,21-94 +35-35,35-66 +4-97,4-98 +2-97,96-97 +14-14,13-50 +3-62,2-54 +3-98,54-98 +24-87,23-86 +29-84,28-78 +42-45,41-55 +8-32,10-33 +35-39,35-77 +10-89,23-59 +10-82,6-98 +52-84,83-84 +65-73,60-72 +7-75,74-91 +50-77,76-93 +1-94,2-95 +98-98,21-97 +19-79,18-24 +3-87,86-88 +47-47,41-48 +28-95,29-96 +71-85,70-72 +60-98,61-75 +3-7,7-96 +22-23,22-50 +90-92,38-91 +83-89,57-88 +6-86,7-87 +3-98,28-99 +52-62,15-62 +23-98,24-24 +38-86,87-94 +10-43,16-42 +17-25,18-76 +60-62,16-63 +66-89,66-88 +42-80,21-79 +6-91,6-93 +8-41,41-41 +80-87,79-99 +88-88,14-89 +35-76,23-75 +8-51,7-88 +2-99,41-71 +6-8,7-99 +18-83,18-19 +69-91,50-68 +28-43,28-29 +57-76,9-58 +56-58,52-57 +13-64,14-81 +6-84,5-83 +95-97,61-77 +9-11,10-12 +46-65,46-66 +18-83,17-83 +86-88,57-87 +15-74,79-99 +5-99,98-99 +13-16,14-69 +23-92,22-98 +70-96,69-98 +9-12,9-13 +10-12,11-52 +21-70,20-87 +44-88,44-84 +84-86,10-85 +30-92,30-91 +10-26,25-79 +42-59,41-42 +39-72,33-99 +19-66,39-66 +21-23,2-80 +23-23,22-23 +73-99,72-97 +4-72,3-5 +22-75,21-76 +24-53,52-52 +40-56,55-64 +17-85,18-84 +15-18,14-85 +8-71,3-8 +1-99,3-95 +41-41,40-96 +60-67,37-68 +9-26,10-91 +30-92,73-92 +44-85,45-86 +13-75,42-75 +11-11,64-83 +7-98,7-99 +53-57,37-54 +71-72,8-71 +86-86,7-86 +14-32,15-54 +13-20,12-12 +68-93,72-94 +3-68,3-4 +4-98,17-97 +15-94,41-83 +23-72,23-72 +26-86,2-27 +36-81,37-55 +10-94,9-93 +32-84,31-83 +44-95,14-45 +3-62,3-62 +46-78,45-66 +96-98,3-97 +91-92,31-92 +50-57,20-58 +1-64,3-64 +48-80,35-48 +69-90,69-91 +62-68,40-67 +74-76,74-76 +42-81,43-82 +16-58,58-59 +88-89,1-89 +68-69,69-90 +57-73,57-68 +58-83,58-94 +2-60,88-94 +14-18,13-20 +68-82,81-83 +77-79,26-78 +20-36,19-99 +12-87,13-89 +54-88,64-87 +12-85,12-86 +1-88,87-89 +43-64,64-81 +38-97,37-48 +12-73,57-74 +25-52,26-53 +22-22,21-37 +75-97,74-76 +13-54,14-32 +16-47,16-48 +9-93,10-92 +50-50,49-88 +10-10,10-76 +94-94,2-95 +33-93,63-92 +46-46,16-47 +90-97,1-91 +24-63,26-63 +38-84,19-62 +28-96,95-98 +56-56,49-58 +6-83,19-82 +31-87,77-88 +4-97,3-99 +13-86,14-85 +90-90,23-90 +8-25,26-26 +17-60,18-89 +10-61,11-62 +13-59,50-59 +52-73,34-73 +94-97,33-95 +20-93,19-97 +6-6,6-94 +7-81,6-89 +4-95,4-95 +9-65,65-66 +37-72,71-75 +57-96,56-72 +23-77,76-76 +7-89,6-88 +1-86,85-86 +42-44,43-93 +18-59,27-58 +19-88,18-95 +1-74,3-73 +22-67,54-66 +23-28,23-27 +6-73,6-73 +4-85,3-5 +46-95,46-96 +5-92,4-86 +22-61,21-61 +70-84,56-95 +8-9,8-85 +18-42,41-41 +12-97,96-97 +67-73,40-74 +13-74,13-81 +3-36,4-98 +8-96,5-6 +9-89,9-84 +67-85,68-84 +68-69,45-69 +34-66,66-71 +50-83,13-82 +31-74,32-83 +1-3,3-83 +4-88,4-4 +12-93,9-94 +70-98,30-98