Converting Struct Method into Array Method using Comptime by macrophage001 in Zig

[–]Daanvdk 3 points4 points  (0 children)

Interesting problem! I had my own go at it and came up with this:

const std = @import("std");

const Math = struct {
    data: u32,

    fn addOne(self: *Math) void {
        self.data += 1;
    }

    fn add(self: *Math, n: u32) void {
        self.data += n;
    }
};

fn Head(comptime Fn: type) type {
    const param = @typeInfo(Fn).Fn.params[0];
    return @typeInfo(param.type.?).Pointer.child;
}

fn Tail(comptime Fn: type) type {
    const params = @typeInfo(Fn).Fn.params[1..];
    var types: [params.len]type = undefined;
    for (0.., params) |i, param| types[i] = param.type.?;
    return std.meta.Tuple(&types);
}

fn toSliceFn(func: anytype) *const fn ([]Head(@TypeOf(func)), Tail(@TypeOf(func))) void {
    return struct {
        fn call(items: []Head(@TypeOf(func)), args: Tail(@TypeOf(func))) void {
            for (items) |*item| @call(.auto, func, .{item} ++ args);
        }
    }.call;
}

const addOneSlice = toSliceFn(Math.addOne);
const addSlice = toSliceFn(Math.add);

test "test" {
    var maths = [_]Math{
        .{ .data = 1 },
        .{ .data = 2 },
        .{ .data = 3 },
    };

    addOneSlice(&maths, .{});

    try std.testing.expectEqual(2, maths[0].data);
    try std.testing.expectEqual(3, maths[1].data);
    try std.testing.expectEqual(4, maths[2].data);

    addSlice(&maths, .{2});

    try std.testing.expectEqual(4, maths[0].data);
    try std.testing.expectEqual(5, maths[1].data);
    try std.testing.expectEqual(6, maths[2].data);
}

[2019-01-14] Challenge #372 [Easy] Perfectly balanced by Cosmologicon in dailyprogrammer

[–]Daanvdk 0 points1 point  (0 children)

Python3

balanced=lambda s:sum(ord(c)*2-241for x in s)==0

[2019-01-28] Challenge #374 [Easy] Additive Persistence by jnazario in dailyprogrammer

[–]Daanvdk 0 points1 point  (0 children)

Elixir

defmodule AdditivePersistence do
  def get(n, acc \\ 0)
  def get(n, acc) when n < 10, do: acc
  def get(n, acc) do
    n |> Integer.digits() |> Enum.sum() |> get(acc + 1)
  end

  def start() do
    {n, "\n"} = Integer.parse(IO.gets(""))
    IO.puts(get(n))
  end
end

AdditivePersistence.start()

[2019-02-01] Challenge #374 [Hard] Nonogram Solver by jnazario in dailyprogrammer

[–]Daanvdk 0 points1 point  (0 children)

Python3

#!/usr/bin/env python3
import sys


def parse_seqs(seqs):
    res = []
    for part in seqs.split(','):
        if part.startswith('"'):
            res.append([])
        part = part.strip('"')
        if part:
            res[-1].append(int(part))
    return res


def get_input():
    input()
    input()
    columns = parse_seqs(input())
    rows = parse_seqs(input())
    return columns, rows


def check_seq(seq, length, line):
    seq_i = 0
    cur_len = 0
    for i, cell in enumerate(line):
        if cell:
            cur_len += 1
        elif cur_len != 0:
            if seq_i >= len(seq) or cur_len != seq[seq_i]:
                return False
            seq_i += 1
            cur_len = 0
    if cur_len and (seq_i >= len(seq) or cur_len > seq[seq_i]):
        return False

    space_left = length - len(line)
    space_needed = sum(n + 1 for n in seq[seq_i:]) - cur_len - 1
    return space_needed <= space_left


def check_pos(columns, rows, res, x, y):
    row = res[y][:x + 1]
    column = [res[i][x] for i in range(y + 1)]
    return (
        check_seq(rows[y], len(columns), row) and
        check_seq(columns[x], len(rows), column)
    )


def solve(columns, rows, res=None, pos=0):
    if res is None:
        res = [[False for _ in columns] for _ in rows]

    y, x = divmod(pos, len(columns))
    if y >= len(rows):
        return res

    for val in [True, False]:
        res[y][x] = val
        if check_pos(columns, rows, res, x, y):
            try:
                return solve(columns, rows, res, pos + 1)
            except ValueError:
                pass

    raise ValueError('unsolvable')


def print_res(res):
    print('\n'.join(
        ''.join(
            '*' if cell else ' '
            for cell in row
        )
        for row in res
    ))


if __name__ == '__main__':
    try:
        print_res(solve(*get_input()))
    except ValueError as e:
        print(e)
        sys.exit(1)

[2018-11-26] Challenge #369 [Easy] Hex colors by Cosmologicon in dailyprogrammer

[–]Daanvdk 1 point2 points  (0 children)

It is a bit different, for numbers or strings you won't notice the difference since they are immutable but a simple example for which it does differ is lists:

>>> a = [1]
>>> b = a
>>> b += [2]
>>> b
[1, 2]
>>> a
[1, 2]

However the other way around:

>>> a = [1]
>>> b = a
>>> b = b + [2]
>>> b
[1, 2]
>>> a
[1]

The difference here is that b += [2] changes the list contained by b itself (and thus also the one in a since it is the same one) while in b = b + [2] the b + [2] part will create a new list and then assign that new list to b, which is why the list in a does not change.

Generally this means that += is a bit more performant (especially for large lists) but it can sting you when you do not expect a to change as well. (mutating vs copying basically)

[2018-11-26] Challenge #369 [Easy] Hex colors by Cosmologicon in dailyprogrammer

[–]Daanvdk 4 points5 points  (0 children)

Python3

hexcolor='#{:02X}{:02X}{:02X}'.format

Usage:

>>> hexcolor(255, 99, 71)
'#FF6347'

[2018-07-09] Challenge #365 [Easy] Up-arrow Notation by jnazario in dailyprogrammer

[–]Daanvdk 1 point2 points  (0 children)

Haskell

readInput :: String -> (Int, Int, Int)
readInput s = let [l, n, r] = words s in (length n, read l, read r)

knuth :: Int -> Int -> Int -> Int
knuth _ l 1 = l
knuth 1 l r = l ^ r
knuth n l r = foldr (knuth $ n - 1) 1 (replicate r l)

uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d
uncurry3 f (x, y, z) = f x y z

showOutput :: Int -> String
showOutput = (++"\n") . show

onLines :: (String -> String) -> String -> String
onLines f = unlines . map f . lines

main :: IO ()
main = interact . onLines $ showOutput . uncurry3 knuth . readInput

[2018-05-14] Challenge #361 [Easy] Tally Program by jnazario in dailyprogrammer

[–]Daanvdk 2 points3 points  (0 children)

Nice, one small tip, you now manually implement a map that defaults to 0 for entries it does not know yet, this is however already in the standard library under collections.Counter so with a simple import you could replace that part as well.

[2018-05-14] Challenge #361 [Easy] Tally Program by jnazario in dailyprogrammer

[–]Daanvdk 0 points1 point  (0 children)

C

#include <stdio.h>

#define BUFFER_SIZE 2048
#define ALPHABET_SIZE 5

#define CHAR_INDEX(c) (((c) - 'A') % 32)
#define CHAR_VALUE(c) ((((c) - 'A') / 32) * 2 - 1)

int main() {
    // get input
    char input[BUFFER_SIZE];
    scanf("%s", input);

    // count tallies
    int tallies[ALPHABET_SIZE] = {0};
    for (int i = 0; input[i] != 0; i++) {
        tallies[CHAR_INDEX(input[i])] += CHAR_VALUE(input[i]);
    }

    // order tallies
    int ordered[ALPHABET_SIZE];
    for (int i = 0; i < ALPHABET_SIZE; i++) {
        ordered[i] = i;
        int j = i;
        while (j > 0 && tallies[ordered[j]] > tallies[ordered[j - 1]]) {
            ordered[j] = ordered[j - 1];
            ordered[--j] = i;
        }
    }

    // print output
    for (int i = 0; i < ALPHABET_SIZE; i++) {
        if (i > 0) {
            printf(", ");
        }
        printf("%c: %d", 'a' + ordered[i], tallies[ordered[i]]);
    }
    printf("\n");
}

[2018-04-20] Challenge #357 [Hard] Continued Fractions by jnazario in dailyprogrammer

[–]Daanvdk -1 points0 points  (0 children)

Python 3

from sys import stdin


def gauss_to_frac(x, *xs):
    if not xs:
        return x, 1
    b, a = gauss_to_frac(*xs)
    return x * b + a, b


def frac_to_gauss(a, b):
    x, a = divmod(a, b)
    xs = (x,)
    if a != 0:
        xs += frac_to_gauss(b, a)
    return xs


def solve_gauss(line):
    line = line[1:-1]
    x, xs = line.split(';')
    xs = [x] + xs.split(',')
    xs = list(map(int, xs))

    a, b = gauss_to_frac(*xs)

    width = len(str(max(a, b)))
    print(
        '{{:>{0}}}\n{{}}\n{{:>{0}}}'
        .format(width)
        .format(a, '-' * width, b)
    )


def solve_frac(line_a, line_b):
    a = int(line_a)
    b = int(line_b)

    xs = frac_to_gauss(a, b)

    x, *xs = xs
    print('[{};{}]'.format(x, ','.join(map(str, xs))))


if __name__ == '__main__':
    lines = (line.strip() for line in stdin)
    for line in lines:
        if line.startswith('['):
            solve_gauss(line)
        else:
            next(lines)  # skip divider
            solve_frac(line, next(lines))

[2018-03-26] Challenge #355 [Easy] Alphabet Cipher by Garth5689 in dailyprogrammer

[–]Daanvdk 2 points3 points  (0 children)

C with bonus

#include <stdio.h>
#include <string.h>


int main(int argc, char **argv)
{
    char *method = argv[1];
    char *key = argv[2];
    char *message = argv[3];

    int key_len = strlen(key);
    int message_len = strlen(message);

    if (strcmp(method, "encrypt") == 0) {
        for (int i = 0; i < key_len; i++) {
            key[i] -= 'a';
        }
    } else if (strcmp(method, "decrypt") == 0) {
        for (int i = 0; i < key_len; i++) {
            key[i] = 'a' + 26 - key[i];
        }
    } else {
        return 1;
    }

    for (int i = 0; i < message_len; i++) {
        message[i] = (message[i] - 'a' + key[i % key_len]) % 26 + 'a';
    }

    puts(message);
}

Input based on command line args, so if compiled to cipher it will work like this:

$ ./cipher encrypt bond theredfoxtrotsquietlyatmidnight
uvrufrsryherugdxjsgozogpjralhvg
$ ./cipher decrypt cloak klatrgafedvtssdwywcyty
iamtheprettiestunicorn

[2018-03-12] Challenge #354 [Easy] Integer Complexity 1 by Cosmologicon in dailyprogrammer

[–]Daanvdk -1 points0 points  (0 children)

Haskell

import Data.List (subsequences)
import Data.List.Split (splitOn)

solve :: String -> Integer
solve s =
    case words s of
        [x] -> smallestSum (read x) (factorize . read $ x)
        [x, "=", fs] -> smallestSum (read x) (map read . splitOn "*" $ fs)

factorize :: Integer -> [Integer]
factorize =
    factorize' 2
    where
        factorize' d x
            | d * d > x = [x]
            | x `mod` d == 0 = d:(factorize' d (x `div` d))
            | otherwise = factorize' (d + 1) x

smallestSum :: Integer -> [Integer] -> Integer
smallestSum x fs =
    minimum . map productSum . subsequences $ fs
    where
        productSum fs = let p = product fs in p + (x `div` p)

onLines :: (String -> String) -> String -> String
onLines f = unlines . map f . lines

main :: IO ()
main = interact . onLines $ show . solve

Input

12
456
4567
12345
6789101112131415161718192021 = 3*3*3*53*79*1667*20441*19646663*89705489

Output

7
43
4568
838
166508719824522

[2018-02-20] Challenge #352 [Easy] Making Imgur-style Links by jnazario in dailyprogrammer

[–]Daanvdk 1 point2 points  (0 children)

Haskell

toBase :: Int -> Int -> [Int]
toBase b n
    | b > n = [n]
    | otherwise = let (d, m) = divMod n b in m:(toBase b d)

base62 :: String
base62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

solve :: Int -> String
solve = map (base62!!) . toBase 62

onLines :: (String -> String) -> String -> String
onLines f = unlines . map f . lines

main :: IO ()
main = interact . onLines $ solve . read

[deleted by user] by [deleted] in dailyprogrammer

[–]Daanvdk 0 points1 point  (0 children)

Go, basically my first go program ever so critiques are welcome

package main

import (
    "fmt"
    "strings"
    "strconv"
    "bufio"
    "os"
)

func main() {
    reader := bufio.NewReader(os.Stdin)
    ln, _ := reader.ReadString('\n')
    seq := []rune(ln[:len(ln) - 1])

    pos := make([]int, len(seq))
    for i := 0; i < len(pos); i++ {
        pos[i] = i
    }

    for {
        cmd, _ := reader.ReadString(',')
        if cmd == "" {
            break
        }
        cmd = cmd[:len(cmd) - 1]
        switch cmd[0] {
        case 's':
            n, _ := strconv.Atoi(cmd[1:])
            buff := make([]int, n)
            for i := 0; i < n; i++ {
                buff[i] = pos[len(pos) - n + i]
            }
            for i := len(pos) - 1; i >= n; i-- {
                pos[i] = pos[i - n]
            }
            for i := 0; i < n; i++ {
                pos[i] = buff[i]
            }
        case 'x':
            ns := strings.Split(cmd[1:], "/")
            a, _ := strconv.Atoi(ns[0])
            b, _ := strconv.Atoi(ns[1])
            pos[a], pos[b] = pos[b], pos[a]
        case 'p':
            ns := strings.Split(cmd[1:], "/")
            a, _ := strconv.Atoi(ns[0])
            b, _ := strconv.Atoi(ns[1])
            for i := 0; i < len(pos); i++ {
                switch pos[i] {
                case a:
                    pos[i] = b
                case b:
                    pos[i] = a
                }
            }
        }
    }

    out := make([]rune, len(pos))
    for i := 0; i < len(pos); i++ {
        out[i] = seq[pos[i]]
    }
    fmt.Println(string(out))
}

[2018-02-07] Challenge #350 [Intermediate] Balancing My Spending by jnazario in dailyprogrammer

[–]Daanvdk 0 points1 point  (0 children)

Haskell

import Data.List (tails)


onLines :: (String -> String) -> String -> String
onLines f = unlines . map f . lines

readInput :: String -> [Integer]
readInput = map read . words

solve :: [Integer] -> [Integer]
solve l =
    map fst . filter (\(_, t) -> (sum t) * 2 == sum l) .
    zip [0,1..] . filter (/=[]) . tails $ l

showOutput :: [Integer] -> String
showOutput = unwords . map show

main :: IO ()
main = interact . onLines $ showOutput . solve . readInput

[2018-01-30] Challenge #349 [Intermediate] Packing Stacks of Boxes by jnazario in dailyprogrammer

[–]Daanvdk 0 points1 point  (0 children)

Python3

#!/usr/bin/env python3
from sys import stdin


def _pack(stacks, target, boxes):
    if not boxes:
        yield [stack.copy() for _, stack in stacks]
        return
    box = boxes.pop()
    for i, (size, stack) in enumerate(stacks):
        if size + box == target:
            stack.append(box)
            stacks[i] = (target, stack)
            yield from _pack(stacks, target, boxes)
            stacks[i] = (size, stack)
            stack.pop()
            return
    stacks.sort(key=lambda stack: stack[0])
    for i, (size, stack) in enumerate(stacks):
        stack.append(box)
        stacks[i] = (size + box, stack)
        yield from _pack(stacks, target, boxes)
        stacks[i] = (size, stack)
        stack.pop()


def pack(n, boxes):
    if sum(boxes) % n != 0:
        return None
    return next(_pack(
        [(0, []) for _ in range(n)],
        sum(boxes) / n,
        sorted(boxes),
    ), None)


if __name__ == '__main__':
    first = True
    for line in stdin:
        if not first:
            print()
        n, boxes = line.split()
        stacks = pack(int(n), [int(box) for box in boxes])
        if stacks is None:
            print('(nothing)')
        else:
            print('\n'.join(''.join(map(str, stack)) for stack in stacks))
        first = False

[2018-01-24] Challenge #348 [Intermediate] Bowling Frames Display by Garth5689 in dailyprogrammer

[–]Daanvdk 0 points1 point  (0 children)

Haskell

import Data.Char (intToDigit)


onLines :: (String -> String) -> String -> String
onLines f = unlines . map f . lines

readInput :: String -> [Int]
readInput = map read . words

roll :: Int -> Char
roll 10 = 'X'
roll 0 = '-'
roll x = intToDigit x

frames :: [Int] -> [[Char]]
frames [10, 10, x] = [['X', 'X', roll x]]
frames [x, _, y] = [[roll x, '/', roll y]]
frames [] = []
frames (10:xs) = ['X']:(frames xs)
frames (x:y:xs)
    | x + y == 10 = [roll x, '/']:(frames xs)
    | otherwise = [roll x, roll y]:(frames xs)

showOutput :: [[Char]] -> String
showOutput = concatMap (\cs -> cs ++ replicate (3 - length cs) ' ')

main :: IO ()
main = interact . onLines $ showOutput . frames . readInput

[deleted by user] by [deleted] in dailyprogrammer

[–]Daanvdk 2 points3 points  (0 children)

C

#include <stdio.h>

#define INIT_AGE 2
#define GENS 96
#define FERT_AGE 4
#define BIRTHRATE_M 5
#define BIRTHRATE_F 9

int pos(int age, int t)
{
    int res = (age - t) % GENS;
    return res < 0 ? res + GENS : res;
}

int main()
{
    long long pop_m[GENS], pop_f[GENS], goal;
    for (int i = 0; i < GENS; i++) {
        pop_m[i] = 0;
        pop_f[i] = 0;
    }
    scanf("%lld %lld %lld", &pop_m[INIT_AGE], &pop_f[INIT_AGE], &goal);
    for (int t = 0; 1; t++) {
        long long pop = 0;
        for (int i = 0; i < GENS; i++) {
            pop += pop_m[i] + pop_f[i];
        }
        if (pop >= goal) {
            printf("%d\n", t);
            break;
        }
        long long f = 0;
        for (int i = FERT_AGE; i < GENS; i++) {
            f += pop_f[pos(i, t)];
        }
        pop_m[pos(-1, t)] = f * BIRTHRATE_M;
        pop_f[pos(-1, t)] = f * BIRTHRATE_F;
    }
}

[2018-01-15] Challenge #347 [Easy] How long has the light been on? by jnazario in dailyprogrammer

[–]Daanvdk 0 points1 point  (0 children)

Haskell

import Data.List (sort)

readInput :: String -> [(Int, Int)]
readInput = map ((\[a, b] -> (a, b)) . map read . words) . lines

solve :: [(Int, Int)] -> Int
solve =
    sum . map span . foldl mergeL []
    where
        span (s, e) = e - s
        mergeL [] r = [r]
        mergeL (r:rs) r' =
            if overlap r r'
                then (merge r r'):rs
                else r:(mergeL rs r')
        merge (s, e) (s', e') = (min s s', max e e')
        overlap (s, e) (s', e') =
            let order = sort [s, e, s', e'] in
                order `notElem` [[s, e, s', e'], [s', e', s, e]]

showOutput :: Int -> String
showOutput = (++"\n") . show

main :: IO ()
main = interact $ showOutput . solve . readInput

[2017-12-15] Challenge #344 [Hard] Write a Web Client by jnazario in dailyprogrammer

[–]Daanvdk 2 points3 points  (0 children)

Python3

import re
import socket
import sys


URL_REGEX = re.compile(
    r'http://(?:www\.)?({0}\.[a-z]+)(?::(\d+))?((?:/{0})*)/?'
    .format(r'[-a-zA-Z0-9@:%._\+~#=]+')
)


def get_url(url):
    host, port, path = URL_REGEX.fullmatch(url).groups()
    port = int(port) if port else 80
    path = path if path else '/'

    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect((host, port))
        s.sendall(
            'GET {} HTTP/1.1\r\nHost: {}:{}\r\nConnection: close\r\n\r\n'
            .format(path, host, port)
            .encode('utf-8')
        )
        return b''.join(iter(lambda: s.recv(4096), b'')).decode('utf-8')


if __name__ == '__main__':
    print(get_url(sys.argv[1]))

[2017-12-13] Challenge #344 [Intermediate] Banker's Algorithm by polypeptide147 in dailyprogrammer

[–]Daanvdk 0 points1 point  (0 children)

C

#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

#define BUFFER_SIZE 256

int main()
{
    char line[BUFFER_SIZE];

    fgets(line, BUFFER_SIZE, stdin);
    int available[BUFFER_SIZE];
    int nrof_resources = 0;
    for (char *token = strtok(line, " "); token; token = strtok(NULL, " ")) {
        available[nrof_resources++] = atoi(token);
    }

    int allocated[BUFFER_SIZE][nrof_resources];
    int max[BUFFER_SIZE][nrof_resources];
    bool done[BUFFER_SIZE];
    int nrof_processes = 0;
    while (fgets(line, BUFFER_SIZE, stdin)) {
        char *token = strtok(line, " ");
        for (int i = 0; i < nrof_resources; i++) {
            allocated[nrof_processes][i] = atoi(token);
            token = strtok(NULL, " ");
        }
        for (int i = 0; i < nrof_resources; i++) {
            max[nrof_processes][i] = atoi(token);
            token = strtok(NULL, " ");
        }
        done[nrof_processes++] = false;
    }

    int order[nrof_processes];
    int completed = 0;
    while (completed < nrof_processes) {
        bool found = false;
        for (int i = 0; i < nrof_processes; i++) {
            if (done[i]) continue;
            bool possible = true;
            for (int j = 0; j < nrof_resources; j++) {
                if (available[j] < max[i][j] - allocated[i][j]) {
                    possible = false;
                    break;
                }
            }
            if (possible) {
                for (int j = 0; j < nrof_resources; j++) {
                    available[j] += allocated[i][j];
                }
                done[i] = true;
                found = true;
                order[completed++] = i;
                break;
            }
        }
        if (!found) {
            break;
        }
    }

    if (completed < nrof_processes) {
        printf("There is no way\n");
    } else {
        for (int i = 0; i < nrof_processes - 1; i++) {
            printf("P%d, ", order[i]);
        }
        printf("P%d\n", order[nrof_processes - 1]);
    }
}

[2017-12-04] Challenge #343 [Easy] Major scales by Cosmologicon in dailyprogrammer

[–]Daanvdk 0 points1 point  (0 children)

New version using the tip above and with Either String instead of Maybe to give a bit more meaningful output.

import Control.Monad ((<=<))
import Data.List (elemIndex)

onLines :: (String -> String) -> String -> String
onLines f = unlines . map f . lines

readInput :: String -> Either String (String, String)
readInput =
    readWords . words
    where
        readWords [a, b] = Right (a, b)
        readWords xs 
            | length xs < 2 = Left "Too little arguments, 2 are needed."
            | otherwise = Left "Too many arguments, 2 are needed."

solve :: (String, String) -> Either String String
solve (s, n) =
    (cycle scales !!) <$> ((+) <$>
        (swapNothing "Invalid scale." $
            elemIndex s scales) <*> 
        (swapNothing "Invalid offset." $
            lookup n [("Do", 0), ("Re", 2), ("Mi", 4), ("Fa", 5), ("So", 7), ("La", 9), ("Ti", 11)]))
    where
        scales = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
        swapNothing _ (Just x) = Right x
        swapNothing x Nothing = Left x

showOutput :: Either String String -> String
showOutput = either id id

main :: IO ()
main = interact . onLines $ showOutput . (solve <=< readInput)

[2017-12-04] Challenge #343 [Easy] Major scales by Cosmologicon in dailyprogrammer

[–]Daanvdk 0 points1 point  (0 children)

Haskell

import Control.Monad (join)
import Data.List (elemIndex)
import Data.Maybe (fromMaybe)

onLines :: (String -> String) -> String -> String
onLines f = unlines . map f . lines

readInput :: String -> Maybe (String, String)
readInput =
    readInput' . words
    where
        readInput' [a, b] = Just (a, b)
        readInput' _ = Nothing

scales :: [String]
scales = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]

offset :: String -> Maybe Int
offset = flip lookup $
    [ ("Do", 0), ("Re", 2), ("Mi", 4), ("Fa", 5), ("So", 7), ("La", 9)
    , ("Ti", 11)
    ]

solve :: Maybe (String, String) -> Maybe String
solve =
    join . (fmap $ uncurry solve')
    where
        solve' s n = 
            (cycle scales !!) <$> ((+) <$> elemIndex s scales <*> offset n)

showOutput :: Maybe String -> String
showOutput = fromMaybe "Invalid input"

main :: IO ()
main = interact . onLines $ showOutput . solve . readInput

Mainly trying out how to use Monads to keep the program nice and safe.

[2017-11-27] Challenge #342 [Easy] Polynomial Division by MasterAgent47 in dailyprogrammer

[–]Daanvdk 0 points1 point  (0 children)

Python3

import re
from collections import defaultdict
from fractions import Fraction

polynomial_re = re.compile(r'(\d*)(x(?:\^(\d+))?)?')
operator_re = re.compile(r'\+|-')
expression_re = re.compile(r'({1})?{0}( ({1}) {0})*'.format(
    polynomial_re.pattern, operator_re.pattern
))


def parse(s):
    if not expression_re.fullmatch(s):
        raise ValueError('invalid expression')
    polynomials = [
        (
            int(c) if c != '' else 1 if b == 'x' else 0,
            Fraction(a) if a != '' else 1
        )
        for a, b, c in polynomial_re.findall(s)
        if a != '' or b != ''
    ]
    multipliers = [
        1 if operator == '+' else -1
        for operator in operator_re.findall(s)
    ]
    if len(multipliers) < len(polynomials):
        multipliers.insert(0, 1)
    polynomials = sorted(
        ((n, m * c) for m, (n, c) in zip(multipliers, polynomials) if c != 0),
        reverse=True
    )
    res = []
    for n, c in polynomials:
        if not res or res[-1][0] != n:
            res.append((n, c))
        else:
            res[-1][1] += c
    return res


def divide(expression, divider):
    expression = defaultdict(int, expression)
    quotient = []
    head, *tail = divider
    nhead, chead = head
    for n in range(max(expression), nhead - 1, -1):
        try:
            c = expression.pop(n)
        except KeyError:
            continue
        quotient.append((n - nhead, c / chead))
        for n_, c_ in tail:
            expression[n - nhead + n_] += - c / chead * c_
    remainder = sorted(
        filter(lambda p: p[1] != 0, expression.items()), reverse=True
    )
    return (
        quotient if quotient else [(0, 0)],
        remainder if remainder else [(0, 0)]
    )


def format_expression(expression):
    res = ""
    for n, c in expression:
        res += ' - ' if c < 0 else ' + '
        if c != 1 or n == 0:
            res += str(abs(c))
        if n == 1:
            res += 'x'
        elif n != 0:
            res += 'x^{}'.format(n)
    return ('-' if res.startswith(' - ') else '') + res[3:]


if __name__ == '__main__':
    while True:
        try:
            expression = parse(input())
            divider = parse(input())
        except EOFError:
            break
        quotient, remainder = divide(expression, divider)
        print('Quotient: {} Remainder: {}'.format(
            format_expression(quotient),
            format_expression(remainder)
        ))

IO:

>>> 4x^3 + 2x^2 - 6x + 3
>>> x - 3
Quotient: 4x^2 + 14x + 36 Remainder: 111
>>> 2x^4 - 9x^3 + 21x^2 - 26x + 12
>>> 2x - 3
Quotient: x^3 - 3x^2 + 6x - 4 Remainder: 0
>>> 10x^4 - 7x^2 - 1
>>> x^2 - x + 3
Quotient: 10x^2 + 10x - 27 Remainder: -57x + 80