From 855375ea18c67773837eecbc9c820efb42302905 Mon Sep 17 00:00:00 2001 From: zgrep Date: Sat, 19 Jun 2021 16:50:03 -0400 Subject: [PATCH] Numbers and files, oh my! --- fractran.py | 144 +++++++++++++++++++++++++++++++++++++++++++++ happybot/common.sh | 36 ++++++++++++ 2 files changed, 180 insertions(+) create mode 100755 fractran.py diff --git a/fractran.py b/fractran.py new file mode 100755 index 0000000..1ac2d57 --- /dev/null +++ b/fractran.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 + +from subprocess import Popen, PIPE +import re + +def cmd(args): + proc = Popen(args, stdout=PIPE) + while True: + line = proc.stdout.readline() + if line: + try: + yield str(line[:-1], 'utf-8', 'ignore') + except: + pass + else: + break + +def irc(chan): + global trigger + fdir = '/home/zgrep/offtopiabday/irc.freenode.net/' + chan + fin = fdir + '/in' + fout = fdir + '/out' + + for line in cmd(['tail', '-n', '0', '-f', fout]): + date, time, nick, line = line.split(' ', 3) + print(line) + m = re.match(r'(?i)(?:happy|hate)bot[:,]\s+([0-9]+)\s+(fractrand?)\s+([0-9]+/[0-9]+(?:,?\s+[0-9]+/[0-9]+)*)$', line) + if m: + n, f, fs = m.group(1), m.group(2), m.group(3) + print('Matched!', n, f, fs) + trigger = True + r = doit(f, n, fs) + trigger = False + r = '\u200b' + r + print('Result!', r) + with open(fin, 'w') as fh: + fh.write(r + '\n') + +from fractions import Fraction +from random import choice +import signal + +trigger = False + +class TimeoutException(Exception): pass +def signal_handler(signum, frame): + global trigger + if trigger: + raise TimeoutException("Timed out!") + +def fractran(n, fracs): + vals = [n] + signal.alarm(1) + try: + while True: + for frac in fracs: + n2 = n*frac + if n2.denominator == 1: + n = n2.numerator + if n in vals: + i = vals.index(n) + return 'Infinite loop: ..., ' + ', '.join(map(str, vals[i:])) + vals.append(n) + break + else: + if len(vals) > 12: + beg = ', '.join(map(str, vals[:2])) + end = ', '.join(map(str, vals[-10:])) + return f'{beg}, ..., {end}' + else: + return ', '.join(map(str, vals)) + except TimeoutException: + if len(vals) > 12: + beg = ', '.join(map(str, vals[:10])) + end = ', '.join(map(str, vals[-2:])) + return f'Timed out: {beg}, ..., {end}, ...' + else: + return 'Timed out: ', + ', '.join(map(str, vals)) + +def random_unordered_fractran(n, fracs): + vals = [n] + signal.alarm(1) + try: + while True: + ns = [ n * frac for frac in fracs ] + ns = [ m for m in ns if m.denominator == 1 ] + if not ns: + if len(vals) > 12: + beg = ', '.join(map(str, vals[:2])) + end = ', '.join(map(str, vals[-10:])) + return f'{beg}, ..., {end}' + else: + return ', '.join(map(str, vals)) + n = choice(ns) + vals.append(n) + except TimeoutException: + if len(vals) > 12: + beg = ', '.join(map(str, vals[:10])) + end = ', '.join(map(str, vals[-2:])) + return f'Timed out: {beg}, ..., {end}, ...' + else: + return 'Timed out: ', + ', '.join(map(str, vals)) + +def main(): + from sys import argv + if len(argv) == 2: + # IRC mode. + irc(argv[1]) + elif len(argv) == 4: + # cli mode. + print(doit(argv[1], argv[2], argv[3])) + else: + print('Wrong number of arguments.') + exit(1) + +def doit(func, inp, args): + n, fracs = None, None + try: + n = int(inp) + except: + return 'Input is not an integer?' + try: + fracs = [Fraction(*map(int, x.split('/', 1))) for x in args.replace(',', '').split()] + except: + return 'Could not parse fraction list.' + + if func == 'fractran': + func = fractran + elif func == 'fractrand': + func = random_unordered_fractran + else: + return f'Invalid function: {func}' + + signal.signal(signal.SIGALRM, signal_handler) + try: + return func(n, fracs) + except TimeoutException: + return 'Timed out.' + except Exception as e: + return 'Some error occurred: ' + str (e) + return 'Something went wrong.' + +if __name__ == '__main__': + main() diff --git a/happybot/common.sh b/happybot/common.sh index 822c7d3..f91a8c9 100644 --- a/happybot/common.sh +++ b/happybot/common.sh @@ -77,3 +77,39 @@ rand() { person() { shuf -n100 "$serv/$chan/out" | grep -v -- '-!-' | rand | awk '{print$3}' | sed 's/^<\|>$//g'; } + +kvnum() { + ( + flock -s 200 + sed 's/ .*//' "$1" | grep -Fnx -e "$2" | sed 's/:.*//' + ) 200>"$1.lock" +} + +kvget() { + num="$(kvnum "$1" "$2")" + if ! [ -z "$num" ]; then + sed -n "$num"'s/^\([^ ]* \)* //p' "$1" + fi +} + +kvset() { + num="$(kvnum "$1" "$2")" + if [ -z "$num" ]; then + var "$2 $3" >> "$1" + else + printf '' > "$1.new" + if [ "$num" != "1" ]; then + sed -n '1,'"$(($num - 1))"'p' "$1" >> "$1.new" + fi + var "$2 $3" >> "$1.new" + sed -n "$(($num + 1))"',$p' "$1" >> "$1.new" + mv -f "$1.new" "$1" + fi +} + +kvdel() { + num="$(kvnum "$1" "$2")" + if ! [ -z "$num" ]; then + sed -i "$num"'d' "$1" + fi +}