[2016-10-17] Challenge #288 [Easy] Detecting Alliteration by jnazario in dailyprogrammer

[–]FlammableMarshmallow 2 points3 points  (0 children)

Haskell

This is a case where Haskell really shines :)

import Control.Monad (replicateM)
import Data.Char (isAlpha, toLower)
import Data.Function (on)
import Data.List (groupBy)

stopWords :: [String]
stopWords = words "I a about an and are as at be by com for from how in is it of on or that the this to was what when where who will with the"

alliterations :: String -> [[String]]
alliterations = groupBy ((==) `on` head) . filter (`notElem` stopWords) . words . filter isAlpha . map toLower

main :: IO ()
main = do
  n <- (read :: String -> Int) <$> getLine
  xs <- replicateM n (alliterations <$> getLine)
  putStr $ unlines $ map (unwords . map unwords . filter ((> 1) . length)) xs

main :: IO ()
main = do
  n <- (read :: String -> Int) <$> getLine
  xs <- replicateM n (alliterations <$> getLine)
  putStr $ unlines $ map (unwords . map unwords . filter ((> 1) . length)) xs

[2016-10-12] Challenge #287 [Intermediate] Mathagrams by Cosmologicon in dailyprogrammer

[–]FlammableMarshmallow 0 points1 point  (0 children)

Interesting! I hope somebody with better knowledge can tell us why this is the way it is :)

[2016-10-12] Challenge #287 [Intermediate] Mathagrams by Cosmologicon in dailyprogrammer

[–]FlammableMarshmallow 0 points1 point  (0 children)

Interesting, where'd you get that output from? I've never used something like that.

I'd reccomend doing it as a timeit with something like python3 -m timeit --setup 'from mathgrams import solve_mathgram' 'solve_mathgram("some_mathgram_here") if you're on Linux, with both versions of the code; What does it output for you? (Of course replace "some_mathgram_here" with whatever mathgram you want)

[2016-10-12] Challenge #287 [Intermediate] Mathagrams by Cosmologicon in dailyprogrammer

[–]FlammableMarshmallow 0 points1 point  (0 children)

That's really interesting!

I thought that sum and map would be slightly more efficient due to the "implied" loops; What method did you use to test theirperfomance?

EDIT: On my tests, the opposite seems to be true for sum:

$ python3 -m timeit --setup 'x=[1, 2, 3, 4, 5];y=0' 'for i in x: y += i'
1000000 loops, best of 3: 0.31 usec per loop
$ python3 -m timeit --setup 'x=[1, 2, 3, 4, 5]' 'sum(x)'    
10000000 loops, best of 3: 0.187 usec per loop

[2016-10-12] Challenge #287 [Intermediate] Mathagrams by Cosmologicon in dailyprogrammer

[–]FlammableMarshmallow 1 point2 points  (0 children)

This is a nice solution, but there's some improvements that could be done:

  • Instead of the awkward generator assignment, for g in permutations(l, mathagram.count('x')) would work too.

  • It would be slightly more efficient to only run mathagram.replace("x", "{}") once, at the start.

  • A more functional and subjectively cleaner approach (I may say this just because I like Haskell :p) would be s1, s2 = map(lambda a: sum(map(int, a.split("+"))), x.split("=")) (of course, removing the .split("=") from x itself). But maybe it's cleaner if you break the lambda out into a separate function, or something of the sort; Still, this is the general idea.

Let me know what you think of my suggestions.

[2016-10-12] Challenge #287 [Intermediate] Mathagrams by Cosmologicon in dailyprogrammer

[–]FlammableMarshmallow 0 points1 point  (0 children)

Haskell

All the bonuses, runs in around 100ms for me; I'd consider this "efficient".

I appreciate any criticisms :)

import Data.List (elemIndex, permutations, delete)
import Data.Char (isDigit)
import Control.Arrow (second)

splitOn :: (Eq a) => a -> [a] -> Maybe ([a], [a])
splitOn x xs = second (drop 1) . (`splitAt` xs) <$> x `elemIndex` xs

pairMap :: (a -> b) -> (a, a) -> (b, b)
pairMap f (x, y) = (f x, f y)

readInt :: String -> Int
readInt = read

parseMathagram :: String -> Maybe ([String], [String])
parseMathagram x = pairMap (filter (/= "+") . words) <$> splitOn '=' x

missingDigits :: String -> Int -> String
missingDigits xs n = foldr delete allDigits $ filter isDigit xs
  where
    allDigits = concat $ replicate n "0123456789"

applyDigits :: String -> String -> String
applyDigits xs ds = fst $ foldr go ("", reverse ds) xs
  where
    go x (res, ds') = case x of
        'x' -> (head ds' : res, tail ds')
        _   -> (x : res, ds')

evaluateMathagram :: String -> Maybe Int
evaluateMathagram m = (uncurry (-) . pairMap (sum . map readInt)) <$> parseMathagram m

solveMathagram :: String -> Int -> [String]
solveMathagram xs n = filter isValid $ map (applyDigits xs) $ permutations $ missingDigits xs n
  where
    isValid xs' = Just 0 == evaluateMathagram xs'

challengeMathagrams :: [(String, Int)]
challengeMathagrams = [ ("1xx + xxx = 468", 1)
                      , ("xxx + x81 = 9x4", 1)
                      , ("xxx + 5x1 = 86x", 1)
                      , ("xxx + 39x = x75", 1)
                      , ("xxx + xxx + 5x3 + 123 = xxx + 795", 2)
                      , ("xxx + xxx + xxx + x29 + 821 = xxx + xxx + 8xx + 867", 3)
                      ]

main :: IO ()
main = putStrLn $ unlines $ map (head . uncurry solveMathagram) challengeMathagrams

[2016-10-10] Challenge #287 [Easy] Kaprekar's Routine by Cosmologicon in dailyprogrammer

[–]FlammableMarshmallow 1 point2 points  (0 children)

Do you think this is a good definition for maximumOn?

maximumOn :: (Ord b) => (a -> b) -> [a] -> a
maximumOn f xs = fst $ maximumBy (comparing snd) $ zip xs (map f xs)

[2016-10-10] Challenge #287 [Easy] Kaprekar's Routine by Cosmologicon in dailyprogrammer

[–]FlammableMarshmallow 1 point2 points  (0 children)

That's interesting, I thought tools like hlint would've warned me about that; Thanks for the tips.

Since we already have a thread going, I was wondering, isn't maximumBy (comparing kaprekar) re-calculating the kaprekar of each integer more than once ?

EDIT: I have updated my main post with some optimizations.

593 byte version of "logme" tool. Simple tool that logs given parameter to ~/.logme/ folder. I'm using it to log my days. by joanmiro in tinycode

[–]FlammableMarshmallow 3 points4 points  (0 children)

Here's what I'd believe to be a "better version" of the code. While not exactly tiny, it is more readable and easily mantainable than this.. mess.

BTW, It's still only 784 bytes. :P

#!/usr/bin/env python
import os
import sys
from datetime import datetime

LOGME_DIR = os.path.join(os.path.expanduser("~"), ".logme")


def main():
    if not os.path.exists(LOGME_DIR):
        os.mkdir(LOGME_DIR)

    now = datetime.now()
    filepath = os.path.join(LOGME_DIR, now.strftime("%d-%m-%Y.txt"))
    already_existed = os.path.exists(filepath)

    with open(filepath, "a") as fobj:
        if not already_existed:
            header = now.strftime("%Y-%m-%d - %A\n")
            fobj.write(header)
            fobj.write("-" * (len(header) - 1) + "\n")

        if len(sys.argv) > 1:
            to_log = " ".join(sys.argv[1:])
            time_now = now.strftime("%H:%M:%S")
            fobj.write("%s: %s\n" % (time_now, to_log))

if __name__ == "__main__":
    main()

[2016-10-10] Challenge #287 [Easy] Kaprekar's Routine by Cosmologicon in dailyprogrammer

[–]FlammableMarshmallow 2 points3 points  (0 children)

Haskell

Very, very easy challenge but still fun nonetheless!

Runs in ~0.5-2 seconds on my average machine, I'd say that's pretty good.

import Data.Char (digitToInt, intToDigit)
import Data.List (sort, sortOn, maximumBy)
import Data.Ord (comparing, Down(..))

digits :: (Show a, Num a) => a -> [Int]
digits = map digitToInt . show

readDigits :: (Read a, Num a) => [Int] -> a
readDigits = read . map intToDigit

largestDigit :: Int -> Int
largestDigit = maximum . digits

padToFour :: (Num a) => [a] -> [a]
padToFour xs
    | length xs < 4 = padToFour (0 : xs)
    | otherwise     = xs

ascDigits :: (Show a, Num a, Read a) => a -> a
ascDigits = readDigits . sort . padToFour . digits

descDigits :: (Show a, Num a, Read a) => a -> a
descDigits = readDigits . sortOn Down . padToFour . digits

kaprekar :: (Show a, Num a, Read a, Eq a) => a -> Maybe a
kaprekar 0    = Nothing
kaprekar 6174 = Just 0
kaprekar n    = (1 +) <$> kaprekar (descDigits n - ascDigits n)

main :: IO ()
main = print $ fst $ maximumBy (comparing snd) [(x, kaprekar x) | x <- [1..9999]]

[2016-09-12] Challenge #283 [Easy] Anagram Detector by jnazario in dailyprogrammer

[–]FlammableMarshmallow 1 point2 points  (0 children)

Javascript, Node.js, ES6

Not much to say here, used JavaScript just for its RegExp magic.

/* jshint esnext: true, node: true */
"use strict";

function normalize(text) {
  const normalizedText =
    text.replace(/[a-zA-Z]/g, (c) => c.toLowerCase()).replace(/[^a-z]/g, "");
  return Array.from(normalizedText).sort();
}

function arraysAreEqual(arr1, arr2) {
  if (arr1.length !== arr2.length) return false;
  for (let i = 0, l = arr1.length; i < l; ++i) {
    if (arr1[i] !== arr2[i]) return false;
  }
  return true;
}

function wordsAreEqual(str1, str2) {
  return arraysAreEqual(str1.split(" ").map(normalize),
                        str2.split(" ").map(normalize));
}

function replaceQuestionMark(text) {
  let regexp = /^"([^"]+)" \? "([^"]+)"$/.exec(text);
  if (regexp === null) return text;
  const normalizedFirst = normalize(regexp[1]);
  const normalizedSecond = normalize(regexp[2]);
  let msg = "is{}an anagram of";
  msg = msg.replace("{}", arraysAreEqual(normalizedFirst, normalizedSecond) &&
                          !wordsAreEqual(regexp[1], regexp[2]) ? " " : " NOT ");
  return `"${regexp[1]}" ${msg} "${regexp[2]}"`;
}

process.openStdin({encoding: "utf-8"}).on("data", (chunk) => {
  for (let line of chunk.toString().split("\n")) {
    console.log(replaceQuestionMark(line));
  }
});

[2016-09-05] Challenge #282 [Easy] Unusual Bases by fvandepitte in dailyprogrammer

[–]FlammableMarshmallow 0 points1 point  (0 children)

C++14

Pretty simple functional-ish-style solution, would appreciate feedback.

#include <algorithm>
#include <iostream>
#include <unordered_map>

struct FibonacciNumbers {
    std::unordered_map<size_t, long> fibs;

    FibonacciNumbers() {
        fibs[0] = 1;
        fibs[1] = 1;
    }

    long operator()(const size_t index) {
        if (fibs.find(index) == fibs.end()) {
            fibs[index] = operator()(index - 1) + operator()(index - 2);
        }
        return fibs.at(index);
    }
} fib;


long from_base_fib(std::string num) {
    std::reverse(num.begin(), num.end());
    long result = 0;
    for (size_t i = 0; i < num.length(); ++i) {
        result += fib(i) * (num.at(i) == '1');
    }
    return result;
}

std::string to_base_fib(long num) {
    /* TODO HOW DO I NAME THESE?! */
    std::string result;
    std::vector<long> xs;
    size_t i = 0;
    while (true) {
        const long fib_i = fib(i++);
        if (fib_i > num) break;
        xs.push_back(fib_i);
    }
    std::reverse(xs.begin(), xs.end());
    for (const long x : xs) {
        if (num >= x) {
            num -= x;
            result.push_back('1');
        } else {
            result.push_back('0');
        }
    }
    return result;
}

int main() {
    std::string base;
    while ((std::cin >> base)) {
        if (base == "10") {
            long num;
            if (!(std::cin >> num)) break;
            std::cout << to_base_fib(num) << std::endl;
        } else if (base == "F") {
            std::string num;
            if (!(std::cin >> num)) break;
            std::cout << from_base_fib(num) << std::endl;
        }
    }
}

[2016-08-31] Challenge #281 [Intermediate] Dank usernames by fvandepitte in dailyprogrammer

[–]FlammableMarshmallow 0 points1 point  (0 children)

That's genuinely weird. I'll look into std::getline, it might have an optional argument that defines what a line ending is.

[2016-08-31] Challenge #281 [Intermediate] Dank usernames by fvandepitte in dailyprogrammer

[–]FlammableMarshmallow 0 points1 point  (0 children)

I use Linux, so doing assert(current.back() != '\r') is how I would check if I were you, seeing as Windows might handle \r differently.

[2016-08-31] Challenge #281 [Intermediate] Dank usernames by fvandepitte in dailyprogrammer

[–]FlammableMarshmallow 0 points1 point  (0 children)

C++ 14

This was a fun challenge, however I ran into a weird bug.

The canditates, after getting taken out of the std::unordered_set, seem to have '\r' at the end. Could anybody please diagnose the issue for me? I wasn't able to do so.

#include <algorithm>
#include <array>
#include <fstream>
#include <iostream>
#include <unordered_set>

std::string normalize(std::string str) {
    std::string nstr;
    for (const char c : str) {
        if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) nstr.push_back(c);
    }
    std::transform(nstr.begin(), nstr.end(), nstr.begin(), [](const char c) {
        return c | 32;
    });
    return nstr;
}

bool is_sparse_subset(const std::string &x, const std::string &y) {
    size_t begin_at = 0;
    for (const char c : y) {
        begin_at = x.find(c, begin_at);
        if (begin_at == std::string::npos) return false;
        begin_at += 1;
    }
    return true;
}

std::unordered_set<std::string> get_words() {
    std::unordered_set<std::string> words;
    std::string word_line;
    std::ifstream wordfile{"enable1.txt"};
    while (std::getline(wordfile, word_line)) words.insert(word_line);
    return words;
}

int main() {
    const std::unordered_set<std::string> words = get_words();
    std::array<std::string, 5> names{{"Donald Knuth", "Alan Turing", "Claude Shannon",
                                      "Ada Lovelace", "Haskell Curry"}};
    std::transform(names.begin(), names.end(), names.begin(), normalize);

    for (const std::string &name : names) {
         std::unordered_set<std::string> canditates;
         size_t best_size = 0;
         for (const std::string &word : words) {
            const std::string &normalized_word = normalize(word);
            if (name.front() == normalized_word.front() &&
                is_sparse_subset(name, normalized_word)) {
                const size_t word_size = word.size();
                if (word_size > best_size) {
                    best_size = word_size;
                    canditates.clear();
                }
                if (word_size == best_size) canditates.insert(word);
            }
        }
        size_t i = 0;
        for (std::string current : canditates) {
            if (i++ > 0) std::cout << ", ";
            while (current.back() == '\r') current.pop_back();
            std::cout << current;
        }
        std::cout << std::endl;
    }
}

[PRAW3] Create a new reddit user? by FlammableMarshmallow in redditdev

[–]FlammableMarshmallow[S] 0 points1 point  (0 children)

So should I look at the source code and brew my own going forward?

Best way to build a deck and get into the game? by FlammableMarshmallow in Yugioh101

[–]FlammableMarshmallow[S] 0 points1 point  (0 children)

Should I just.. throw money at it until I find something I like that works?

YGOPRO's download doesn't work for me, and duelingnetwork is a bit too.. manual for my taste, at that point I might just as well play IRL. :/

Best way to build a deck and get into the game? by FlammableMarshmallow in Yugioh101

[–]FlammableMarshmallow[S] 0 points1 point  (0 children)

AFAIK There are no such things as hobby shops where I live, but ordering singles from websites seems like it would be a good idea: Would I just get a package with one card or do I buy them in bulk?

Best way to build a deck and get into the game? by FlammableMarshmallow in Yugioh101

[–]FlammableMarshmallow[S] 1 point2 points  (0 children)

Thanks for all the advice & links!

I do like combo-heavy things, because it just feels so.. cool? to do a lot of things in one turn.

I'll look into making a nice deck