Daily Programming Challenge:

Programming (no configs, no support)
Forum rules
Only original work ;)
User avatar
DebianJoe
Frame Buffer
Posts: 1915
Joined: Mon Jul 01, 2013 5:41 am
Location: emacs.d

Re: Daily Programming Challenge:

Unread post by DebianJoe » Thu Dec 04, 2014 9:30 am

Thanks Zazen! I'm still 98% sure that I SHOULD have used local variables for the in-function checks. I tried it a few different ways, and kept being told that 'let' was passed too few arguments. I'm heading back to the books to figure out how I could have done it better.
|>>BBQ Roaster, Alpha Branch<< | >> clinky << | >> X11 must die << |
Thanks BASIC

User avatar
GekkoP
Emacs Sancho Panza
Posts: 5877
Joined: Tue Sep 03, 2013 7:05 am

Re: Daily Programming Challenge:

Unread post by GekkoP » Thu Dec 04, 2014 10:37 am

Code: Select all

(def win-over {:scissors [:paper :lizard]
               :paper [:rock :spock]
               :rock [:lizard :scissors]
               :lizard [:spock :paper]
               :spock [:rock :scissors]})

(defn b-win? [a b]
  (not (nil? (some #{a} (b win-over)))))

(defn a-win? [a b]
  (not (nil? (some #{b} (a win-over)))))

(defn tie? [a b]
  (= a b))

(defn play [a b]
  (cond (a-win? a b)
        (println "Player 1 wins")

        (b-win? a b)
        (println "Player 2 wins")

        (tie? a b)
        (println "Tie!")

        :else
        (println "WTF!?")))
In action:

Code: Select all

user> (play :spock :rock)
Player 1 wins
nil
user> (play :spock :lizard)
Player 2 wins
nil
user> (play :spock :spock)
Tie!
nil
user> (play :DebianJoe :Haskell)
WTF!?
nil
@Joe: I think that is the correct let syntax. It is similar to what I use in Clojure.

User avatar
simgin
Meme Fodder
Posts: 1167
Joined: Sun Jan 06, 2013 12:07 am
Location: Bradford-on-Avon, UK

Re: Daily Programming Challenge:

Unread post by simgin » Thu Dec 04, 2014 2:08 pm

^ Hehe Play DebianJoe Haskell :D
Someone told me that I am delusional, I almost fell off my unicorn.

pidsley
Hermit
Posts: 2539
Joined: Wed Oct 17, 2012 12:31 pm

Re: Daily Programming Challenge:

Unread post by pidsley » Thu Dec 04, 2014 7:03 pm

Code: Select all

#!/bin/bash

getnum() {
    names=( rock spock paper lizard scissors )

    i=0 
    while [[ $i < 5 ]]; do
        [[ $1 == ${names[$i]} ]] && break;
        let i++
    done
    if [[ $i == 5 ]]; then
        echo "$1 is not a valid play"
        exit 1
    fi  
    return $i
}

getnum $1; p1=$?
getnum $2; p2=$?

ans=$(((5+p1-p2)%5))

case $ans in
    0 ) echo tie! ;;  
    1|2 ) echo $1 wins ;;  
    2|4 ) echo $2 wins ;;  
esac

Code: Select all

$ ./rkp lizard spock
lizard wins
$ ./rkp spock rock
spock wins
$ ./rkp rock rock
tie!
$ ./rkp rock scissors
rock wins
$ ./rkp scissors paper
scissors wins
$ ./rkp paper rock
paper wins
$ ./rkp rock gekko
gekko is not a valid play

User avatar
GekkoP
Emacs Sancho Panza
Posts: 5877
Joined: Tue Sep 03, 2013 7:05 am

Re: Daily Programming Challenge:

Unread post by GekkoP » Thu Dec 04, 2014 7:08 pm

^ fantastic. Clean and simple.
(also: not valid, huh? :D)

User avatar
DebianJoe
Frame Buffer
Posts: 1915
Joined: Mon Jul 01, 2013 5:41 am
Location: emacs.d

Re: Daily Programming Challenge:

Unread post by DebianJoe » Fri Dec 05, 2014 7:47 am

I love it! All of them. When I look at someone else's answer and say things like "Well, Pidsley used an array and looping...and I bet I could have mapped a list and produced similar results without using literals in a conditional switch....." or "Well, I like how GP's code didn't use the same determination methods for winner that mine did." or "Zazen23's answer is fun with it's use of included verbs and randoms." Well, that makes me rethink how I did something, and how it could have been done better. I'll probably have a 'make your existing work cooler' challenge later.

Anyhow "Today's Challenge"
Image

Normal Mode - Make a single function that when fed a number 'n', returns 'n^th' position of the Fibonacci sequence.

Focus Group Mode - Your original was awesome, but 72% of the target audience have a personal objection to your methods due to religious reasons. The boss, who doesn't even know what Fibonacci sequence means, has requested a total rewrite, using an entirely different method in the same language. Do it, but complain about it.

Fib in-depth @ wolfram-alpha.
|>>BBQ Roaster, Alpha Branch<< | >> clinky << | >> X11 must die << |
Thanks BASIC

User avatar
DebianJoe
Frame Buffer
Posts: 1915
Joined: Mon Jul 01, 2013 5:41 am
Location: emacs.d

Re: Daily Programming Challenge:

Unread post by DebianJoe » Fri Dec 05, 2014 8:09 am

Code: Select all

;; Recursive Method
(define (fib n)
  (cond 
   ((< n 1) 0)
   ((= n 1) 1)
   (else 
    (+ (fib (- n 1))
       (fib (- n 2))))))

;; Iterating Loop Method
(define (fib n)
  ;; WTF?  Religious opposition to Recusion? ;;
  ;; where is this BS being marketed?        ;;
  (define count 0)
  (let loop ((a 0) (b 1) (count n))
    (if (= count 0)
      a
      (loop b (+ a b) (- count 1)))))
* "Named Let" totally in yesterday's research about 'let' syntax. I learned a cool trick, but now I have more questions about how these structures are allocated in memory. What is the default allocation for implicitly declared global/free values? So many questions....
|>>BBQ Roaster, Alpha Branch<< | >> clinky << | >> X11 must die << |
Thanks BASIC

User avatar
GekkoP
Emacs Sancho Panza
Posts: 5877
Joined: Tue Sep 03, 2013 7:05 am

Re: Daily Programming Challenge:

Unread post by GekkoP » Fri Dec 05, 2014 10:28 am

Since my first method is basically a shameless Clojure version of Joe's recursive method (also, it is the first way I learnt how to code Fibonacci through recursion...), I go straight with the other solution. Learnt about this one when studying lazy sequences and iterate. And again, map comes to the rescue.

Code: Select all

(defn infinite-fibo []
  (map first (iterate (fn [[a b]] [b ( + a b)]) [0N 1N])))

(defn fibonacci [n]
  (take n (infinite-fibo)))
In action:

Code: Select all

user> (fibonacci 10)
(0N 1N 1N 2N 3N 5N 8N 13N 21N 34N)
This is not my solution to the problem, but something I studied to better understand map and lazy sequences in Clojure. Honestly, I only knew to solutions to get a Fibonacci series: recursive one, and loop/iterate one. Joe already covered them both.

A note: just when I thought "Hey, this is super cool", a more elegant solution that avoids BigInt shows up. Also, there are plenty of other ways to do it. Yep, my path to enlightenment is still at its very first steps.

pidsley
Hermit
Posts: 2539
Joined: Wed Oct 17, 2012 12:31 pm

Re: Daily Programming Challenge:

Unread post by pidsley » Fri Dec 05, 2014 3:41 pm

Fortran

Code: Select all

      integer function fib(n)
      integer r, a, b, i 
      r = 0
      a = 0
      b = 1
      do 10 i = 2, n
         r = a + b
         a = b
         b = r
  10  continue
      fib = b     
      end  

      program main
      integer fib
      print *, fib(6)
      end
Haskell

Code: Select all

fib :: Integer -> Integer
fib n
    | n == 0 = 0
    | n == 1 = 1
    | otherwise = fib (n-1) + fib (n-2)

main = print (fib 6)

User avatar
DebianJoe
Frame Buffer
Posts: 1915
Joined: Mon Jul 01, 2013 5:41 am
Location: emacs.d

Re: Daily Programming Challenge:

Unread post by DebianJoe » Fri Dec 05, 2014 4:02 pm

Pidsley, how does the "fib :: Integer -> Integer" work? Is that a declare of sorts?

Also, super-clean answers everyone. Gekko totally called me out on taking the easy ones...and I did. :)

I did consider the Scheme special-form 'do', which is pretty cool:

Code: Select all

(do ((vec (make-vector 5))
                (i 0 (+ i 1)))
              ((= i 5) vec)
             (vector-set! vec i i)) 

result > #(0 1 2 3 4)
Edit: So, doing some reading led me to the example in SICP for a tree-recursive Fib sequence. Damn, totally didn't mean to rip that one off (my first example). Accidental bitch-level, achieved! Apologies.

In recompense, allow me to offer this version, which mutates free values via a 'do' loop.

Code: Select all

(define (fib n) (define index 0)
       (do ((a 0) (b 1) (c 1))
	  ((> index n) a)
	 (set! c (+ a b))
	 (set! a b)
	 (set! b c)
	 (set! index (+ index 1))))
|>>BBQ Roaster, Alpha Branch<< | >> clinky << | >> X11 must die << |
Thanks BASIC

pidsley
Hermit
Posts: 2539
Joined: Wed Oct 17, 2012 12:31 pm

Re: Daily Programming Challenge:

Unread post by pidsley » Fri Dec 05, 2014 6:17 pm

DebianJoe wrote:Pidsley, how does the "fib :: Integer -> Integer" work? Is that a declare of sorts?
Yes, of sorts. As I understand it, most of the time it is not necessary to declare function and argument types, but I threw it in there because it is considered good programming practice, it looks interesting, and has many variations that still confuse the hell out of me.

First the parameter type(s), then last the the function return type. So "fib" takes an Integer and returns an Integer. A simple function that takes two integers and returns a string would be:

Code: Select all

same ::  Integer -> Integer -> String
same i j 
    | i == j = "yes"
    | otherwise = "no"
From Learn Haskell Fast and Hard, this explains a little:
Yes, strange. In fact, in Haskell no function really has two arguments. Instead all functions have only one argument. But we will note that taking two arguments is equivalent to taking one argument and returning a function taking the second argument as a parameter.

More precisely f 3 4 is equivalent to (f 3) 4.
I'm sure howmie could give us a better and more accurate explanation; he's actually using Haskell. I'm just playing; I can only barely pretend to understand this stuff.

pidsley
Hermit
Posts: 2539
Joined: Wed Oct 17, 2012 12:31 pm

Re: Daily Programming Challenge:

Unread post by pidsley » Fri Dec 05, 2014 8:21 pm

OK, better late than never, here is FizzBuzz in Haskell:

Code: Select all

fizzval :: Integer -> String
fizzval x
    | x `mod` 15 == 0 = "FizzBuzz"
    | x `mod` 3  == 0 = "Fizz"
    | x `mod` 5  == 0 = "Buzz"
    | otherwise  = show x

main = putStr $ unlines $ map fizzval [1..100]
I admit that I finally cheated and looked at solutions online; this is a combination of several different solutions. I learned a lot both from trying to figure it out on my own and from parsing the solutions.

You will have to trust me that it works, unless you want to try it yourself (the Debian GHC package is only 204M ;). But I would not post a non-working solution.

User avatar
franksinistra
Ivana Fukalot
Posts: 1093
Joined: Mon Jan 27, 2014 2:03 am
Location: 印尼国

Re: Daily Programming Challenge:

Unread post by franksinistra » Fri Dec 05, 2014 10:28 pm

My Solution in Clojure

Solution 1 (Recursive function shamelessly ripped from DJ)

Code: Select all

(defn recur-fibo [n]
  (last (loop [x 1
               y 1
               next [1]]
    (if (>= (count next) n)
      next
      (recur b (+ a b) (conj next b))))))
Second Solution (Using reduce, note that Gekko's iterate solution would be better than this)

Code: Select all

(defn reduce-fibo [n]
  (first (reduce (fn [[a b] _] [b (+ a b)]) [0 1] (range n)))
rice no more.

User avatar
DebianJoe
Frame Buffer
Posts: 1915
Joined: Mon Jul 01, 2013 5:41 am
Location: emacs.d

Re: Daily Programming Challenge:

Unread post by DebianJoe » Sat Dec 06, 2014 12:15 am

I'll admit I'm not testing other solutions at all. I trust everyone to post working solutions. In most cases, I can spot the 'how' something works, except the Haskell solutions. ;)

I may have to get more creative with some of the challenges, as there's really only a couple of sensible ways to solve mathematical problems.
|>>BBQ Roaster, Alpha Branch<< | >> clinky << | >> X11 must die << |
Thanks BASIC

pidsley
Hermit
Posts: 2539
Joined: Wed Oct 17, 2012 12:31 pm

Re: Daily Programming Challenge:

Unread post by pidsley » Sat Dec 06, 2014 12:17 am

And a rather lame but working version of rock-paper-scissors-lizard-spock in Haskell. I'm sure there are better ways I could do this, but I'm pretty happy I got even this much working.

Code: Select all

winner :: String -> String -> String
winner p1name p2name
	| p1 == 0 = (p1name ++ " is not valid")
	| p2 == 0 = (p2name ++ " is not valid")
	| a == 0 = "tie"
	| a < 3 = (p1name ++ " wins")
	| a < 5 = (p2name ++ " wins")
	where 
		a = (p1 - p2) `mod` 5
		p1 = (getnum p1name)
		p2 = (getnum p2name)

getnum :: String -> Integer
getnum n
	| n == "rock" = 1
	| n == "spock" = 2
	| n == "paper" = 3
	| n == "lizard" = 4
	| n == "scissors" = 5
	| otherwise = 0

main = do
    putStrLn "player 1?"
    p1name <- getLine
    putStrLn "player 2?"
    p2name <- getLine

    putStrLn (winner p1name p2name)
I have to admit that I am starting to like this language, even though the magnitude of what I don't know scares me to death. I don't know if I should thank Joe for giving me an interesting challenge, or curse him.

User avatar
simgin
Meme Fodder
Posts: 1167
Joined: Sun Jan 06, 2013 12:07 am
Location: Bradford-on-Avon, UK

Re: Daily Programming Challenge:

Unread post by simgin » Sat Dec 06, 2014 1:33 am

^ wow, I have no clue what so ever, of what is going on there o.O
One thing though, it looks very structured/organised. I can read some c++ and python, but this is far to different for me.
Good work Pidsley :)

cheers
Simon
Someone told me that I am delusional, I almost fell off my unicorn.

User avatar
DebianJoe
Frame Buffer
Posts: 1915
Joined: Mon Jul 01, 2013 5:41 am
Location: emacs.d

Re: Daily Programming Challenge:

Unread post by DebianJoe » Sat Dec 06, 2014 6:52 am

One of the regular issues that I personally come across is "Hey, is that a palindrome?" No more will I manually have to answer this question, as we shall automate it!

Image
This Weekend's Challenge:

Normal Mode: Write a program or function to determine if a word or string of words is a palindrome.

More Useful Mode: The above, but usable as an executable from commandline.
|>>BBQ Roaster, Alpha Branch<< | >> clinky << | >> X11 must die << |
Thanks BASIC

machinebacon
Baconator
Posts: 10253
Joined: Thu Sep 16, 2010 11:03 am
Location: Pfälzerwald
Contact:

Re: Daily Programming Challenge:

Unread post by machinebacon » Sat Dec 06, 2014 7:43 am

Code: Select all

#!/bin/bash
read s
s2=(`echo "$s" | rev`)
echo "Checking $s against $s2"
if [[ ! "$s" == "$s2" ]]; then
echo "No palindrome"
else
echo "Palindrome"
fi
something like this? It's cheating because it uses rev. Sorry :)
(that being said, I am quite sure that Perl or Python have some similar module/built-in. rev is part of util-linux, so it's just a half cheat :) )
..gnutella..

User avatar
DebianJoe
Frame Buffer
Posts: 1915
Joined: Mon Jul 01, 2013 5:41 am
Location: emacs.d

Re: Daily Programming Challenge:

Unread post by DebianJoe » Sat Dec 06, 2014 8:49 am

I accept this. Bash is the art of sub-processes. :)

We may have to get into some benchmarking individual languages some later, as I've been really curious about how Fortran stacks up to Scheme stacks up to Haskell.
|>>BBQ Roaster, Alpha Branch<< | >> clinky << | >> X11 must die << |
Thanks BASIC

User avatar
DebianJoe
Frame Buffer
Posts: 1915
Joined: Mon Jul 01, 2013 5:41 am
Location: emacs.d

Re: Daily Programming Challenge:

Unread post by DebianJoe » Sat Dec 06, 2014 10:04 am

Image

Code: Select all

(define (palindrome? our_word)
  (define (is_palindrome begin end)
    (if (>= begin end) 1
        (and (char=? (string-ref our_word begin) (string-ref our_word end))
             (is_palindrome (+ 1 begin) (- end 1)))))
  (is_palindrome 0 (- (string-length our_word) 1)))
(let ((argv (car (command-line-arguments))))
  (print 
   (string-append argv 
                  (if (palindrome? argv) 
    " --\033[1;32mIS a palindrome\033[1;m\n"
    " --\033[1;31mIS NOT a palindrome\033[1;m\n"))))
I had to pretty much go through the racket documentation, R5RS, etc. to look up how each section needed to work as I'm totally under-prepared for string functions with scheme. I practically cloned an argument vector example, but really....it's not like there is a lot of room for creativity there.
|>>BBQ Roaster, Alpha Branch<< | >> clinky << | >> X11 must die << |
Thanks BASIC

Post Reply