I'm trying to create an octal handling function in Clojure, so far I have this:
(defn octal [a]
(if (= 023 a)
(Integer/toOctalString a)
a))
where I have '023' i would like to replace it with some logic which checks if a number begins with '0'. I'm aware of starts-with? for strings, is there a method for use with numbers?
I'm trying to do it this way as if I pass Integer/toOctalString an integer without a 0 it passes back a larger number. E.g. 2345 becomes 4451.
Thank you
It seems read-string can do this for you:
(read-string "023")
; ==> 19
(read-string "19")
; ==> 19
If you want to read octal without prefix you can simply add the zero before passing it:
(defn octal->integer [s]
(read-string (str \0 s)))
(octal->integer "23")
; ==> 19
When outputting numbers:
The built in format function does this nicely:
user> (format "%o" 19)
"23"
of course nothing about a number knows if it was originally provided in a particular format, though if you put it into a collection and store that information along with it, either directly or in metadata you can keep track of that.
As far as reading numbers is concerned:
Clojure numbers are Octal by default if they start with a leading zero
Just the usual warning that clojure.core/read-string IS TOTALLY UNSAFE to use on untrusted input. It will run code from the string at read time if not carefully managed.
user clojure.edn/read-string instead
They both will read an octal number for you just fine:
user> (clojure.edn/read-string "023")
19
user> (read-string "023")
19
And clojure.edn/read-string will refuse to p0wn your server:
user> (read-string "#=(println \"Pwning your server now\")")
Pwning your server now
nil
user> (clojure.edn/read-string "#=(println \"Pwning your server now\")")
RuntimeException No dispatch macro for: = clojure.lang.Util.runtimeException (Util.java:221)
So it's worth being in the habit of using clojure.edn for all data that it not actually part of your program.
PS: there is a dynamic var you can set to turn off the reader-eval feature of read string, and depending on it is an accident waiting to happen.
Related
I am using Clojure to do the following task -
Write a function named get-divisors which takes a number n as input and returns the all the numbers between 2 and √𝑛 inclusive
I have this code so far, that seems to be working as expected:
(defn get-divisors [n]
(str (range 2 (Math/sqrt n))))
The user inserts and input and the code shall display all numbers between 2 and the square root of that particular number. (I know! get-divisors is a horrible name for the function)
I type (get-divisors 101) I get the following output
"(2 3 4 5 6 7 8 9 10)" which is correct.
However, the issue is when I use the number 4 I get a result of nil or () when I should in-fact get 2. Or when I enter 49 I should get all numbers between 2 and 7 but I only get all the numbers between 2 and 6.
I have searched online for some information. I am new to Clojure however, the information on this programming seems to be scarce as opposed to the likes of Java, JavaScript. I have read another thread which was based on a similar situation to mind, however, the suggestions/answers didn't work for me unfortunately.
I would appreciate any help. Thank you.
Please see the Clojure CheatSheet. range does not include the upper bound. So, in general, you probably want something like
(range 2 (inc n))
or in your case
(range 2 (inc (Math/floor (Math/sqrt n))))
Also check out http://clojure.org
I am a beginner in clojure. I am trying to solve this simple problem on codechef using clojure. Below is my clojure code but this code is taking too long to run and gives TimeoutException. Can someone please help me to optimize this code and make it run faster.
(defn checkCase [str]
(let [len (count str)]
(and (> len 1) (re-matches #"[A-Z]+" str))))
(println (count (filter checkCase (.split (read-line) " "))))
Note: My program is not getting timedout due to input error. On codechef input is handled automatically (probably through input redirection. Please read the question for more details)
Thank you!
Most text finding exercises are exercizes in regexps, this one no different. It's usually pretty hard to find a more efficient way in whatever programming language that will outpace good regexp implementations.
In this case re-seq, look around regexps, repetition limiting and the multiline regexp flag (?m) are your friends
(defn find-acronyms
[s]
(re-seq #"(?m)(?<=\W|^)[A-Z]+(?=\W|$)" s))
(find-acronyms "I like coding and will participate in IOI Then there is ICPC")
=> ("IOI" "ICPC")
Let's dissect the regex:
(?m) The multiline flag: lets you match your regex over multiple lines, so no need to split into multiple strings
(?<=\W|^) The match should follow a non-word character or the beginning of the (multiline) string
[A-Z]{2,} Match concurrent capital letters, a minimum of 2
(?=\W|$) The match should be followed by a non-word character or the end of the (multiline) string
I can only guess that wherever you run this snippet of code, it doesn't feed anything to your read-line invocation. Or maybe it does, but doesn't send a newline as the last thing. So it hangs waiting.
(defn checkCase [str]
(let [len (count str)]
(and (> len 1) (re-matches #"[A-Z]+" str))))
(defn answer [str]
(println (count (filter checkCase (.split str " ")))))
So at the REPL:
=> (answer "GGG fff TTT")
;-> 2
;-> nil
The answer is being printed to the screen. But probably best to have your function return the answer rather than print it out:
(defn answer [str]
(count (filter checkCase (.split str " "))))
All I have done is replaced your (read-line) with an argument. (read-line) is expecting input from stdin and waiting for it forever - or until a timeout happens in your case.
I am not sure if this is the slow part of your code, but if it is your could try to split up the execution and safe gard the very slow regexp part by executing it when it is necessary. I think the current version with AND already does that. If it does not you can try to do something else, like this:
(defn checkCase [^String str]
(cond
(< (.length str) 2)
false
(re-matches #"[A-Z]+" str)
true
:else
false))
maybe you could try using re-seq instead of spltting the string and checking every item? So you will lose the filter, .split, and additional function call. Something like this:
(println (count (re-seq #"\b[A-Z]{2,}?\b" (read-line))))
You need to submit a Java program. You can test it on the command line before you submit it. You can but don't need to use redirection symbols (<,>). Just type the input and see that every time you do it returns the count after you have typed enter.
You will need aot compilation (Ahead Of Time, which means that .class files are included) and a main that is exported. Only then will it become a Java program.
Actually when they ask for a Java program they probably mean a .class file. You can run a .class file with the java program (which I imagine is what their test-runner does). Put it in a shell or batch file when testing, but just submit the .class file.
Various Clojure style guides recommend avoiding lines longer than 80 characters. I am wondering if there is an idiomatic way to avoid long String literals.
While it's common these days to have wide screens, I still agree that long lines should be avoided.
Here are some examples (I'm tempted to follow the first):
;; break the String literal with `str`
(println (str
"The quick brown fox "
"jumps over the lazy dog"))
;; break the String literal with `join`
(println (join " " [
"The quick brown fox"
"jumps over the lazy dog"]))
I am aware that Clojure supports multi-line String literals, but using this approach has the undesired effect of the newline characters being interpreted, e.g. using the repl:
user=> (println "The quick brown fox
#_=> jumps over the lazy dog")
The quick brown fox
jumps over the lazy dog
You should probably store the string inside an external text file, and read the file from your code. If you still feel the need to store the string in your code, go ahead and use str.
EDIT:
As requested, I will demonstrate how you can read long strings at compile time.
(defmacro compile-time-slurp [file]
(slurp file))
Use it like this:
(def long-string (compile-time-slurp "longString.txt"))
You may invent similar macros to handle Java Properties files, XML/JSON configuration, SQL queries, HTML, or whatever else you need.
I find it convenient to use str to create strings and use character literals such as \newline or \tab instead of "\n" to break them.
I rarely violate the 80-column rule this way.
The most idiomatic ways I know of are the following:
1) Use (str) to split the string over multiple lines.
(str "User " (:user context)
" is now logged in.")
This is probably the most idiomatic usage. I've seen this done in multiple libraries and projects. It is fast, since (str) uses a StringBuilder under the hood. It also allows you to mix code in transparently, as I've done in the example.
2) Allow strings to break the 80 char limit by themselves, when it makes sense.
(format
"User %s is now logged in."
(:user context))
Basically, it's ok to break the 80 char limit for strings. Chances are it's less likely you care about reading the string when you work with the code, and on the off chance you need to, exceptionally, you'll need to scroll horizontally.
I've wrapped the string in a (format) here to be able to inject code similarly to my previous example. You don't need to.
Less idiomatic ways would be:
3) Put your strings in files and load them from there.
(slurp "/path/to/userLoggedIn.txt")
With a file: /path/to/userLoggedIn.txt containing:
User logged in.
I advise against this because:
It introduces IO side effects
It has the potential to fail, say the path is wrong, the resource is missing or corrupted, the disk errors, etc.
It has performance implications, disk reads are slow.
Its hard to inject content from code if you need too.
I would say do this only if your text is really big. Or if the content of the string needs to be changed by non devs. Or if the content is obtained externally.
4) Have a namespace where you def all your strings in, and load them from there.
(ns msgs)
(defn logged-in-msg [user]
(format
"User %s is now logged in."
user))
Which you then use like this:
(msgs/logged-in-msg (:user context))
I prefer this over #3. You still need to allow to use #2 here, where it's ok to have strings break the 80 char limit. In fact, here you put strings by themselves on a line, so they are easy to format. If you use code analysis like checkstyle, you can exclude this file from the rule. It also does not suffer from the issues of #3.
If you are going with #3 or #4, you probably have a special use case for your strings, like internationalization, or having business edit them, etc. In those cases, you might be better served building a more robust solution, that could be inspired from the above methods, or using a library that specializes in those use cases.
(defmacro strs
([]
"")
([a]
(if (string? a) `~a `(str ~a)))
([a & more]
`(str
~#(->> (cons a more)
(partition-by string?)
(mapcat #(if (string? (first %)) (cons (apply str %) nil) %))))))
Usage:
(strs "one "
"two "
3
" four" " five")
; => "one two 3 four five"
Neighbouring literal strings will be concatenated at compile time.
I've been trying to get a simple reg-ex working in Clojure to test a string for some SQL reserved words (select, from, where etc.) but just can't get it to work:
(defn areserved? [c]
(re-find #"select|from|where|order by|group by" c))
(I split a string by spaces then go over all the words)
Help would be greatly appreciated,
Thanks!
EDIT: My first goal (after only reading some examples and basic Clojure materials) is to parse a string and return for each part of it (i.e. words) what "job" they have in the statement (a reserved word, a string etc.).
What I have so far:
(use '[clojure.string :only (join split)])
(defn isdigit? [c]
(re-find #"[0-9]" c))
(defn isletter? [c]
(re-find #"[a-zA-Z]" c))
(defn issymbol? [c]
(re-find #"[\(\)\[\]!\.+-><=\?*]" c))
(defn isstring? [c]
(re-find #"[\"']" c))
(defn areserved? [c]
(if (re-find #"select|from|where|order by|group by" c)
true
false))
(defn what-is [token]
(let [c (subs token 0 1)]
(cond
(isletter? c) :word
(areserved? c) :reserved
(isdigit? c) :number
(issymbol? c) :symbol
(isstring? c) :string)))
(defn checkr [token]
{:token token
:type (what-is token)})
(defn goparse [sql-str]
(map checkr (.split sql-str " ")))
Thanks for all the help guys! it's great to see so much support for such a relatively new language (at least for me :) )
I'm not entirely sure what you want exactly, but here's a couple of variations to coerce your first regex match to a boolean:
(defn areserved? [c]
(string?
(re-find #"select|from|where|order by|group by"c)))
(defn areserved? [c]
(if (re-find #"select|from|where|order by|group by"c)
true
false))
UPDATE in response to question edit:
Thanks for posting more code. Unfortunately there are a number of issues here that we could
try to address by patching your existing code in a simplistic and naïve fashion, but it will
only get you so far, before you hit the next problem with this single iteration approach.
#alex is correct, that your areserved? method will fail to match order by if you have already
split your string by white space. That said, a simple fix is to treat order and by as separate keywords (which they are, even though they always appear together).
The next issue is that the areserved? function will match keywords in a string, but you are dispatching it against a character in the what-is function. You nearly always get a match in your cond for isletter?, so you will everything is marked as a 'word'.
All in all, it looks like you are trying to do too much work in a single application of map.
I'm not sure if you are just doing this for fun to play with Clojure (which is admirable - keep going!), in which case, maybe it doesn't matter if you press on with this simple parsing approach... you'll definitely learn something; but if you would like to take it further and parse SQL more successfully, then I would suggest that you may find it helpful to to read a little on Lexing, Parsing and building Abstract Syntax Trees (AST).
Brian Carper has written about using the Java parser generator "ANTLR" from Clojure - it's a few years old, but might be worth looking at.
You also might be able to get some transferrable ideas from this chapter from the F# programming book on lexing and parsing SQL.
I recently started reading Paul Grahams 'On Lisp', and learning learning clojure along with it, so there's probably some really obvious error in here, but I can't see it: (its a project euler problem, obviously)
(ns net.projecteuler.problem31)
(def paths (ref #{}))
; apply fun to all elements of coll for which pred-fun returns true
(defn apply-if [pred-fun fun coll]
(apply fun (filter pred-fun coll)))
(defn make-combination-counter [coin-values]
(fn recurse
([sum] (recurse sum 0 '()))
([max-sum current-sum coin-path]
(if (= max-sum current-sum)
; if we've recursed to the bottom, add current path to paths
(dosync (ref-set paths (conj #paths (sort coin-path))))
; else go on recursing
(apply-if (fn [x] (<= (+ current-sum x) max-sum))
(fn [x] (recurse max-sum (+ x current-sum) (cons x coin-path)))
coin-values)))))
(def count-currency-combinations (make-combination-counter '(1 2 5 10 20 50 100 200)))
(count-currency-combinations 200)
When I run the last line in the REPL, i get the error:
<#CompilerException java.lang.IllegalArgumentException: Wrong number of args passed to: problem31$eval--25$make-combination-counter--27$recurse--29$fn (NO_SOURCE_FILE:0)>
Apart from the question where the error is, the more interesting question would be: How would one debug this? The error message isn't very helpful, and I haven't found a good way to single-step clojure code, and I can't really ask on stack overflow every time I have a problem.
Three tips that might make your life easier here:
Wrong number of args passed to: problem31$eval--25$make-combination-counter--27$recurse--29$fn (NO_SOURCE_FILE:0)>
Tells you roughly where the error occurred: $fn at the end there means anonymous function and it tells you it was declared inside recurse, which was declared inside make-combination-counter. There are two anonymous functions to choose from.
If you save your source-code in a file and execute it as a script it will give you a full stack trace with the line numbers in the file.
at net.projecteuler.problem31$apply_if__9.invoke(problem31.clj:7)
Note you can also examine the last exception and stack trace from within the REPL by examining *e eg: (.stackTrace *e) The stack trace is at first quite daunting because it throws up all the Java internals. You need to learn to ignore those and just look for the lines that refer to your code. This is pretty easy in your case as they all start with net.projecteuler
You can name your anonymous functions to help more quickly identify them:
(fn check-max [x] (<= (+ current-sum x) max-sum))
In your case using all this info you can see that apply-if is being passed a single argument function as fun. Apply does this (f [1 2 3]) -> (f 1 2 3). From your comment what you want is map. (map f [1 2 3]) -> (list (f 1) (f 2) (f 3)). When I replace apply with map the program seems to work.
Finally, if you want to examine values you might want to look into clojure-contrib.logging which has some helpers to this effect. There is a spy macro which allows you to wrap an expression, it will return exactly the same expression so it does not affect the result of your function but will print out EXPR = VALUE, which can be handy. Also on the group various people have posted full tracing solutions. And there is always the trusty println. But the key skill here is being able to identify precisely what blew up. Once you know that it is usually clear why, but sometimes printouts are needed when you can't tell what the inputs are.
dont have a REPL on me though it looks like:
(defn apply-if [pred-fun fun coll]
(apply fun (filter pred-fun coll)))
takes a list like '(1 2 3 4 5) filters some of them out '(1 3 5)
and then creates a function call like (fun 1 3 5)
and it looks like it is being called (apply-if (fn [x] with a function that wants to receive a list of numbers as a single argument.
you could change the apply-if function to just pass call to the fun (with out the apply) or you could change the call to it to take a function that takes an arbitrary number of arguments.