Byte collection to string on clojure - string

The following code
(defn caesar-block-cypher
"Computes the caesar block cypher for the given text with the k key. Returns an array of bytes"
[k text]
(let [byte-string (.getBytes text)]
(loop [return-byte-array [] byte-string byte-string]
(if (= '() byte-string)
return-byte-array
(recur
(conj return-byte-array (byte (+ k (first byte-string))))
(rest byte-string))))))
Returns an array of bytes after processing the caesar cipher with key k at text. I want to convert back the byte array to a string or perform the cipher over the string directly, but (new String return-byte-array) doesn't work. Any suggestions?
EDIT: Thanks for the responses. I recodified this on a more functional style (that actually works):
(defn caesar-block-cypher
"Computes the caesar block cypher for the given text with the k key."
[k text & more]
(let [byte-string (.getBytes (apply str text (map str more)))]
(apply str (map #(char (mod (+ (int %) k) 0x100)) byte-string))))

(let [byte-array (caesar-block-cypher 1 "Hello, world!")]
(apply str (map char byte-array)))

Use java's String constructor to create string quickly like this,
(let [b (caesar-block-cypher 1 "Hello World")]
(String. b))

You can use slurp, it also works for byte arrays:
From https://clojuredocs.org/clojure.core/slurp#example-588dd268e4b01f4add58fe33
;; you can read bytes also
(def arr-bytes (into-array Byte/TYPE (range 128)))
(slurp arr-bytes)

AFAIK ceaser chipher just shifts chars why are you dealing with bytes,
(let [s "Attack"
k 1
encoded (map #(char (+ (int %) k)) s)
decoded (map #(char (- (int %) k)) encoded)]
(apply str decoded))

Related

How do I find the number of characters in a string using scheme programming language?

I used string-length to get the number of characters but I am having difficulties in defining a recursive function. Should I convert the string to a list and then count the elements?
There's no useful way of doing this recursively (or even tail recursively): strings in Scheme are objects which know how long they are. There would be such an approach in a language like C where strings don't know how long they are but are delimited by some special marker. So for instance if (special-marker? s i) told you whether the i'th element of s was the special marker object, then you could write a function to know how long the string was:
(define (silly-string-length s)
(let silly-string-length-loop ([i 1])
(if (special-marker? s i)
(- i 1)
(silly-string-length-loop (+ i 1)))))
But now think about how you would implement special-marker? in Scheme: in particular here's the obvious implementation:
(define (special-marker? s i)
(= i (+ (string-length s) 1)))
And you can see that silly-string-length is now just a terrible version of string-length.
Well, if you wanted to make it look even more terrible, you could, as you suggest, convert a string to a list and then compute the length of the lists. Lists are delimited by a special marker object, () so this approach is reasonable:
(define (length-of-list l)
(let length-of-list-loop ([i 0]
[lt l])
(if (null? lt)
i
(length-of-list-loop (+ i 1) (rest lt)))))
So you could write
(define (superficially-less-silly-string-length s)
(length-of-list
(turn-string-into-list s)))
But, wait, how do you write turn-string-into-list? Well, something like this perhaps:
(define (turn-string-into-list s)
(let ([l (string-length s)])
(let loop ([i 0]
[r '()])
(if (= i l)
(reverse r)
(loop (+ i 1)
(cons (string-ref s i) r))))))
And this ... uses string-length.
What is the problem with?
(string-length string)
If the question is a puzzle "count characters in a string without using string-length",
then maybe:
(define (my-string-length s)
(define (my-string-length t n)
(if (string=? s t) n
(my-string-length
(string-append t (string (string-ref s n))) (+ n 1))))
(my-string-length "" 0))
or:
(define (my-string-length s)
(define (my-string-length n)
(define (try thunk)
(call/cc (lambda (k)
(with-exception-handler (lambda (x)
(k n))
thunk))))
(try (lambda ()
(string-ref s n)
(my-string-length (+ n 1)))))
(my-string-length 0))
(but of course string-ref will be using the base string-length or equivalent)

How to modify string by index in Clojure?

I want to modify a string by applying a function to some of its chars (by starting index and length).
For example, I want to increment the ascii representation of the string "aaaaa" from the 2nd index to the 4th.
[start=1 length=3]
"aaaaa" => "abbba"
The only way I could think of is applying map, but it goes over all the sequence.
You could use subs to get the portions you do and don't want to modify. After modification use str to concatenate the result together:
(defn replace-in-str [f in from len]
(let [before (subs in 0 from)
after (subs in (+ from len))
being-replaced (subs in from (+ from len))
replaced (f being-replaced)]
(str before replaced after)))
You can call it:
(replace-in-str
(fn [sub-str] (apply str (map #(char (+ 1 (int %))) sub-str)))
"aaaaa"
1
3)
Indeed map applies the function to every element in the sequence. One way to get around that is to start with map-indexed. Unlike map, map-indexed passes the element's index as the first argument to the mapping function. When we have element's index, we can use it to choose if we need to perform the operation or just return the element as is.
A solution might look like this:
(defn inc-char [c]
(char (inc (long c))))
(defn if-in-range [from to f]
(fn [i x & args]
(if (<= from i (dec to))
(apply f x args)
x)))
(defn map-subs [from to f s]
(apply str (map-indexed (if-in-range from to f) s)))
(map-subs 1 4 inc-char "aaaaa")
;; "abbba"
I thought of using map-index to execute the operation only on the specified index:
((fn [op start length] (map-indexed (fn [i m] (if (<= start i length)
(op m)
m)) "aaaaa"))
#(char (+ 1 (int %)))
1
3)
=> (\a \b \b \b \a)
Here you go:
(defn replace-str
[s start-i end-i]
(apply str (map-indexed (fn [index val]
(if (and (>= index start-i)
(<= index end-i))
(char (+ (int val) 1))
val))
s)))
(replace-str "aaaa" 1 2)
;=> "abba"

Scheme: How to find a position of a char in a string

I am trying to find the index of a string where it is equal to a certain character, but I can seem to figure it out.
This is what I got so far, but its not working...
(define getPos
(lambda ()
(define s (apply string-append myList))
(getPosition pos (string->list s))))
(define getPosition
(lambda (position s)
(if (and (< position (length s)) (equal? (car s) #\space))
((set! pos (+ pos 1)) (getPosition (cdr s) pos));increment the positon and continue the loop
pos)));else
(define length
(lambda (s);the value s must be coverted to a string->list when passed in
(cond
((null? s) 0)
(else (+ 1 (length (cdr s)))))))
The solution is simple: we have to test each char in the list until either we run out of elements or we find the first occurrence of the char, keeping track of which position we're in.
Your proposed solution looks weird, in Scheme we try to avoid set! and other operations that mutate data - the way to go, is by using recursion to traverse the list of chars. Something like this is preferred:
(define (getPosition char-list char pos)
(cond ((null? char-list) #f) ; list was empty
((char=? char (car char-list)) pos) ; we found it!
(else (getPosition (cdr char-list) char (add1 pos))))) ; char was not found
For 0-based indexes use it like this, converting the string to a list of chars and initializing the position in 0:
(getPosition (string->list "abcde") #\e 0)
=> 4
Of course, we can do better by using existing procedures - here's a more idiomatic solution:
(require srfi/1) ; required for using the `list-index` procedure
(define (getPosition string char)
(list-index (curry char=? char)
(string->list string)))
(getPosition "abcde" #\e)
=> 4
A solution with for:
#lang racket
(define (find-char c s)
(for/first ([x s] ; for each character in the string c
[i (in-naturals)] ; counts 0, 1, 2, ...
#:when (char=? c x))
i))
(find-char #\o "hello world")
(find-char #\x "hello world")
Output:
4
#f

Idiomatic string rotation in Clojure

How to idiomatically rotate a string in Clojure for the Burrows-Wheeler transform?
I came up with this, which uses (cycle "string"), but feels a bit imperative:
(let [s (str "^" "banana" "|")
l (count s)
c (cycle s)
m (map #(take l (drop % c)) (range l))]
(apply map str m))
=> ("^banana|" "banana|^" "anana|^b" "nana|^ba" "ana|^ban" "na|^bana" "a|^banan" "|^banana")
I'm not sure if this qualifies as code golf. Is there a cleaner way to do this?
I would do:
(defn bwrot [s]
(let [s (str "^" s "|")]
(for [i (range (count s))]
(str (subs s i) (subs s 0 i)))))
or:
(defn bwrot [s]
(let [n (+ 2 (count s))
s (str "^" s "|^" s "|")]
(for [i (range n)]
(subs s i (+ i n)))))
The second one should allocate less (one string instead of three per iteration).
There used to be a rotations function in clojure.contrib.seq that might be worth a look for inspiration. The source is reproduced below:
(defn rotations
"Returns a lazy seq of all rotations of a seq"
[x]
(if (seq x)
(map
(fn [n _]
(lazy-cat (drop n x) (take n x)))
(iterate inc 0) x)
(list nil)))
Then you could do something like:
(apply map str (rotations "^banana|"))
; => ("^banana|" "banana|^" "anana|^b" "nana|^ba" "ana|^ban" "na|^bana" "a|^banan" "|^banana")
A stepped call to partition works:
(defn bwt[s]
(let [s' (str "^" s "|")
c (cycle s')
l (count s')]
(map last (sort (apply map str (take l (partition l 1 c)))))))
(apply str (bwt "banana"))
=> "|bnn^aaa"
If I was unconcerned about efficiency or number of characters I'd write something like:
(defn rotate-string
[s]
(apply str (concat (drop 1 s) (take 1 s))))
(defn string-rotations
[s]
(->> s
(iterate rotate-string)
(take (count s))))
(rotate-string "^banana|") ; "banana|^"
(string-rotations "^banana|") ; ("^banana|" "banana|^" "anana|^b" "nana|^ba" "ana|^ban" "na|^bana" "a|^banan" "|^banana")
In particular, factoring out the single rotation into its own function.
Another way to accomplish rotation is to use a "double string" (i.e. concatenate the string to itself) and play around with substrings.
(defn rotations [strng]
(let [indices (range (count strng))
doublestr (str strng strng)]
(map #(subs doublestr % (+ % (count strng))) indices)))
(rotations "^banana|")
;;(^banana| banana|^ anana|^b nana|^ba ana|^ban na|^bana a|^banan |^banana)
Rotations of "foo":
Take the double string "foofoo"
Length n of "foo" = 3
The rotations are all the n substrings of "foofoo" that start with indices 0, 1, 2 and have the same length n

Want more Clojure way to brute force string match

I've implementing a brute force string matching algorithm in Clojure. It works as it should, but what I'm looking for is how to make this code "cleaner," and more readable. Note that I also have to have the algorithm print out how it's doing the character comparisons. I don't know about all the conventions to pay attention to, and I'd really like some tips on how to write Clojure better.
What it does: It takes a piece of text, and for each of it's indexes (since the text is of a type String), match it with the input string. If there's a match, we compare the second character to the next index of the text. It's a lot to explain in English, but if you run the program, it prints out what it's doing.
The code:
(defn underscores [n]
(apply str (repeat n "_")))
(defn brute_force_string_match
"Receives text as string type as its first argument,
string in second argument, brute force matches the
string to the text. Assumes text is longer than string."
[text
string]
;; for loop
;; i is 1 less than the amount of No matches you will get
(loop [i 0
j_and_matches [0 0]]
;;outer loop stops when i > n -m
(if (and
(<= i (- (count text) (count string)))
(not= (j_and_matches 0) (count string)))
;; the "while loop"
(do
(println "")
(print "\nPos = " i "\n"text"\n"
(str (underscores i) string))
(recur
(inc i)
(loop [j 0
print_pos i
undscore_amt 0
matches (j_and_matches 1)]
(if (and
(< j (count string))
(= (.charAt string j) (.charAt text (+ i j))))
(do
(print "\n" (str (str (underscores print_pos)) "^ Match! "))
(recur (inc j)
(inc print_pos)
(inc undscore_amt)
(inc matches)))
(do
(if (not= j (count string))
(print "\n" (str (str (underscores print_pos)) "^ No Match ")))
[j matches])))))
(if (= (j_and_matches 0) (count string))
(do (println "\n Pattern found at position " (dec i))
(println "The number of comparisons: " (+ (j_and_matches 1) (dec i)))
(dec i))
-1))))
For one thing, j has no place in your outer loop, which has i go through the possible start points for a match. j is the local index into string while testing it against the text starting from i.
I'd write it something like this:
(defn brute_force_string_match [text string]
(let [last-start (- (count text) (count string))]
(loop [i 0, matches []]
(if (> i last-start)
matches
(let [match?
(loop [j 0]
(or (= j (count string))
(and (= (.charAt string j) (.charAt text (+ i j)))
(recur (inc j)))))]
(recur (inc i) (if match? (conj matches i) matches)))))))
Apart from the superfluous j in your outer loop, I don't know that yours is significantly different from this.
As a matter of style,
I've bound the complex inner loop expression to local match?. This keeps the final
line clear.
I've used and and or to simplify the conditionals in that expression.
I've pushed down the conditional (if match? ... ) into an argument of the
outer recur.
Note
You can use get instead of .charAt to access characters of strings.

Resources