Fork me on GitHub
#beginners
<
2019-01-25
>
chase-lambert00:01:22

hello! I'm trying to complete the armstrong numbers exercise on exercism. I think I'm almost there but can't figure out how to finish off my armstrong function. I need to replace the base parameter of my power function so I can allow input of larger numbers. If I manually put in the digits everything else checks out but can't figure out how to do it generically. Obviously this one doesn't run because there is no third function but I just wanted to show what I'm trying to achieve.

(ns armstrong-numbers)

(defn power
  "exponentation function"
  [base exp]
  (reduce * (repeat exp base)))

(defn digits
  "splits up num into digits e.g 153 becomes (1 5 3)"
  [number]
  (map #(Character/digit % 10) (str number)))

(defn armstrong
  "calculates armstrong number"
  [num]
  (let [exp (count (digits num))]
    (reduce + [(power (first (digits num)) exp)
               (power (second (digits num)) exp)
               (power (third (digits num)) exp)])))

(defn armstrong? [num]
  (= num (armstrong num)))

chase-lambert00:01:49

meta question: what's the best way to post long code snippets here?

hiredman00:01:09

change to ', or just use bigdecimals everywhere and checkout the java doc for them (they have a .pow method)

chase-lambert00:01:28

hmmm. I like the self made power function and the math works. I came across it during a different tutorial. But I'm not sure how to figure out how to take my broken up number (1 5 3) and plug it in as the base parameters in that armstrong function. I think it will have to be some kind of recursive check too right? That function is getting a little unwieldy for me to wrap my head around but can't figure out a different approach.

hiredman00:01:41

I may not have understood your question, I assumed you were hitting Long/MAX_LONG and getting an error due to overflow

hiredman00:01:20

ok, I get it

chase-lambert00:01:24

oh no, that's my fault. In that 2nd to last function armstrong where I have that vector of (power (first (digits num)) exp) I need to make the base parameter (first (digits num) into something generic(?) that will take each digit in numbers and make the vector out of them

hiredman00:01:36

by larger number you mean a number with more digits

hiredman00:01:21

You want to turn your manual calling of power on the first digit, then the second, etc in to something that does it automatically on each digit

chase-lambert00:01:28

yup! sorry about that. it needs to take any size number

chase-lambert00:01:57

so if i put in 9494 the vector will have 4 numbers calculated

hiredman00:01:12

so (digits num) returns a sequence of digits, do you know of a function that calls another function for each element of a sequence?

chase-lambert00:01:05

so then I should be looking into how to iterate over every number in the list i get back from digits like (1 5 3) and turn it into a vector that is [(power 1 exp) (power 5 exp) (power 3 exp)] that seems like a good approach, right?

hiredman00:01:40

why are you turning it in to a vector?

chase-lambert00:01:51

to be honest, i don't rightfully know. i was just experimenting in the repl and stumbled into the (reduce + (seq [(power base exp)...]) algorithm giving me the correct armstrong number calculation

chase-lambert00:01:25

isn't that seq portion redundant? lol. thats kind of embarrassing

hiredman00:01:16

it is, reduce (and map, and many other functions) internally call seq on collections you pass in to them

hiredman00:01:51

so you have map, you have a seq of digits, and you now how to sum a seq of numbers, it seems like the missing bit is actually mapping power over the seq of digits, which you cannot do directly because power takes 2 arguments and you are mapping over a single collection so your mapped function only gets a single argument

chase-lambert00:01:55

yeah, so then I'm thinking something with partial so I'm just filling in the base parameter and then the armstrong function will take care of the 2nd parameter? but now I'm getting a bit in over my head

hiredman00:01:24

partial is a good thought, but it doesn't exactly work, because with partial you can only partially apply to the first arguments, but you need to leave the first argument out

hiredman00:01:11

can you write a function that given an exp, returns a function that takes a base and returns (power base exp)

chase-lambert00:01:13

hmmm. yes, i'm going to explore that. i'm wondering if i need to just keep it in my armstrong function and figure out the base part in my let block? let me try and wrap my head around all this. thank you!

chase-lambert00:01:34

i did it! thanks so much hiredman. Not sure if I quite did what you were hinting at but it clicked something in my brain for sure. Here is the revised function:

(defn armstrong
  "calculates armstrong number"
  [num]
  (let [base (digits num)
        exp (repeat (count (digits num)) (count (digits num)))]
    (reduce + (map power base exp))))

chase-lambert00:01:00

that exponent think in the let block looks a little ugly but I'm happy I actually solved it!

seancorfield01:01:40

One neat thing about map is that it will stop at the end of the shortest of the collections it is given, so exp could be the (infinite) sequence (repeat (count (digits num))) and it would still work @chase-lambert

chase-lambert01:01:22

nice! I was thinking it could be cleaned up like that.

manuelrascioni11:01:38

Hi here! I'm playing with clojure focusing on testing, I'm struggling to have a test report as a file listing the test executed, which failed and the output of the failing tests (it would be nice to have in html, or junit-xml format). I was able to generate the junit xml, but apart from the number of test executed/failed, it doesn't have any deeper detail. Do you have this kind of reports? What setup did you did to generate them (library, script, whatever)? Thank you in advance!

borkdude11:01:47

@manuelrascioni maybe you should look into #kaocha

manuelrascioni11:01:40

I've tried with it 🙂 but when a test fails for an exception it doesn't report it in the xml

manuelrascioni11:01:59

Kaocha seems what I need but can't figure out why the junit report is so "poor", I don't know if I misconfigured something or it is a common behavior

borkdude11:01:49

discuss in that channel or make an issue with the lib, I don’t use it myself yet

manuelrascioni11:01:22

ok, thanks for the support!

marko.micic12:01:48

Hi guys, is there a way to use pretty print as code formatter? Something akin to prettier in JS world.

zane18:01:13

If you're willing to use a third-party library for this you'll have lots of options. Here are a couple: • https://github.com/weavejester/cljfmthttps://github.com/kkinnear/zprint

marko.micic09:01:40

Thanks, this is that I was looking for

mfikes13:01:30

@marko.micic I don't know about the built in pretty-printer, but Fipp has support for formatting Clojure code. (See https://github.com/brandonbloom/fipp/blob/master/src/fipp/clojure.cljc)

marko.micic13:01:38

Thank you, this seems useful.