The problem generally appears if I have a class containing, for example, a couple of slots that would be filled with vectors. If I want to make the object of this class more-or-less transparent, I implement print-object for it. And here I am faced with the problem:
If I print everything in one line, REPL's heuristics are not good enough to determine how to arrange printable parts in multiple lines, causing everything to be shifted to the right (see example below).
If I decide to split the output into multiple lines manually, I have a problem of how to indent everything properly, such that if this object is a part of another object, indentation is preserved (see example below for more clarity).
Here is the code. Consider two classes:
(defclass foo ()
((slot1 :initarg :slot1)
(slot2 :initarg :slot2)))
(defclass bar ()
((foo-slot :initarg :foo)))
And I have the following instances:
(defparameter *foo*
(make-instance 'foo
:slot1 '(a b c d e f g h i j k l m n o p q r s t u v)
:slot2 #(1 2 3 4 5 6 7 8)))
(defparameter *bar*
(make-instance 'bar
:foo *foo*))
What I want to see, is something like this:
> *bar*
#<BAR
foo-slot = #<FOO
slot1 = (A B C D E F G H I J K L M N O P Q R S T U V)
slot2 = #(1 2 3 4 5 6 7 8)>>
Case 1: Printing everything in one line
Definitions of print-object for these classes can be something like these:
(defmethod print-object ((obj foo) out)
(with-slots (slot1 slot2) obj
(print-unreadable-object (obj out :type t)
(format out "slot1 = ~A slot2 = ~A" slot1 slot2))))
(defmethod print-object ((obj bar) out)
(with-slots (foo-slot) obj
(print-unreadable-object (obj out :type t)
(format out "foo-slot = ~A" foo-slot))))
However, their printable representation is less than ideal:
> *foo*
#<FOO slot1 = (A B C D E F G H I J K L M N O P Q R S T U V) slot2 = #(1 2 3 4 5
6 7 8)>
> *bar*
#<BAR foo-slot = #<FOO slot1 = (A B C D E F G H I J K L M N O P Q R S T U V) slot2 = #(1
2
3
4
5
6
7
8)>>
Case 2: Attempt to multiple line printing
Using multiple line printing, I don't know how to control indentation:
(defmethod print-object ((obj foo) out)
(with-slots (slot1 slot2) obj
(print-unreadable-object (obj out :type t)
(format out "~%~Tslot1 = ~A~%~Tslot2 = ~A" slot1 slot2))))
(defmethod print-object ((obj bar) out)
(with-slots (foo-slot) obj
(print-unreadable-object (obj out :type t)
(format out "~%~Tfoo-slot = ~A" foo-slot))))
Thus, *foo* prints OK, but *bar* isn't:
> *foo*
#<FOO
slot1 = (A B C D E F G H I J K L M N O P Q R S T U V)
slot2 = #(1 2 3 4 5 6 7 8)>
*bar*
#<BAR
foo-slot = #<FOO
slot1 = (A B C D E F G H I J K L M N O P Q R S T U V)
slot2 = #(1 2 3 4 5 6 7 8)>>
In the past I tried to play around with print-indent, but without a success (I couldn't see any effect from it, maybe wasn't using it correctly, SBCL 1.2.14).
Is there a (preferably simple) way to solve this?
Try something like this (might require more polishing):
(defmethod print-object ((obj foo) out)
(with-slots (slot1 slot2) obj
(print-unreadable-object (obj out :type t)
(format out "~<~:_slot1 = ~A ~:_slot2 = ~A~:>" (list slot1 slot2)))))
(defmethod print-object ((obj bar) out)
(with-slots (foo-slot) obj
(print-unreadable-object (obj out :type t)
(format out "~<~:_foo-slot = ~A~:>" (list foo-slot)))))
It uses ~< and ~:>, which are format operations for logical blocks. Then it uses ~:_, which is a conditional newline. You should read the relevant hyperspec section.
Related
I try to remove 1 whitespace from this string:
m y r e a l n a m e i s d o n a l d d u c k
Expected result:
my real name is donald duck
My code are:
def solve_cipher(input)
input.split('').map { |c| (c.ord - 3).chr }.join(' ') # <- Here I tried everything
end
puts solve_cipher('p| uhdo qdph lv grqdog gxfn')
# => m y r e a l n a m e i s d o n a l d d u c k
I tried everything to solve my problem, example:
input.....join(' ').squeeze(" ").strip # => m y r e a l n a m e...
or
input.....join.gsub(' ','') # => myrealnameisdonaldduck
or
input.....join(' ').lstrip # => m y r e a l n a m e...
and so on...
Well, you could split the string into words first, then split each word into characters. Using the same method you used in your code, it could look like this.
def solve_cipher(input) input.split(' ').map{ |w| w.split('').map { |c| (c.ord - 3).chr}.join('')}.join(' ') end
When joining the characters in the same word, we put no space between them; when joining the words together we put one space between them.
As stated in the question, you are using Rails, so you can also try squish method:
def solve_cipher( input )
input.split(' ').map(&:squish).join(' ')
end
str = "m y r e a l n a m e i s d o n a l d d u c k"
str.gsub(/\s(?!\s)/,'')
#=> "my real name is donald duck"
The regex matches a whitespace character not followed by another whitespace character and replaces the matched characters with empty strings. (?!\s) is a negative lookahead that matches a whitespace.
If more than two spaces may be present between words, first replace three or more spaces with two spaces, as follows.
str = "m y r e a l n a m e i s d o n a l d d u c k"
str.gsub(/\s{3,}/, " ").gsub(/\s(?!\s)/,'')
#=> "my real name is donald duck"
I know that it is not a fancy way of doing it but you could just try to create a new string and have a function traversal(input) with a counter initiated at 0, that would return this new string.
It would go through your input (which is here your string) and if the counter is 0 and it sees a space it just ignores it, increments a counter and go to the next character of the string.
If the counter is different of 0 and it sees a space it just concatenates it to the new string.
And if the counter is different of 0 and it sees something different of a space, it concatenates it to the new string and counter equals 0 again.
The trick is to use a capture group
"m y r e a l n a m e i s d o n a l d d u c k".gsub(/(\s)(.)/, '\2')
=> "my real name is donald duck
Assume that I have the following statements:
A p B, A p C, B p C ( p is a symmetric property, i.e. B p A, C p A and C p B)
A v 2, B v 1, C v 1,
I want to use a rule to do something like:
?a p all(?b)
if ?b v 1
than ?a q 'Yes'
that means that you can infer (A q 'Yes'), but B can't since B p A and A v 2(although B p C and C v 1).
[rule: (?a eg:p ?b), (?b eg:v 1) -> (?a eg:q 'Yes')]
I've used the above rule in Jena, but I got A,B,C eg:q 'Yes', which is wrong.
Any help will be greatly appreciated.
Update (originally posted as an answer)
the meaning of (?a p all(?b)) is that I like to get a set which all ?mem in this set fulfill the (?a p ?mem). And all member must fulfill (?mem v 1) to infer (?a q 'Yes').
For example,
A p B and A p C,so I get a set which contains (B, C).since B and C v 1,so A q 'Yes.
B p A and B p C,so I get a set(A, C),but A v 2,so can't infer that B q 'Yes'.
Problem Solved
Thanks to Joshua Taylor.
Firstly, these two rules can't use at the same time.The rule2 should be used after rule1.
And, the rule2 should be [rule2: (?s ?p ?o) noValue(?s, connectedToNonOne) -> (?s q 'Yes')].
but I got A,B,C eg:q 'Yes', which is wrong.
The rule you have actually written in Jena says
For any two individuals X and Y, if (X p Y) and (Y v 1) then (X q 'Yes').
From the rule you've written, this is correct, by:
(A p C), (C v 1) → (A q 'Yes')
(B p C), (C v 1) → (B q 'Yes')
(C p B), (B v 1) → (C q 'Yes')
What you're actually trying to say is:
For any individual X, if for every individual Y, (X p Y) implies (Y v 1), then (X q 'Yes').
In first order logic, your original rule could be written as:
∀ x,y ([p(x,y) ∧ v(y,1)] → q(x,'yes')
What you're actually trying to capture would be:
∀x[(∀y[p(x,y) → v(y,1)]) → q(x,'yes')]
That's harder to capture in Jena rules, because to check whether (∀y[p(x,y) → v(y,1)]) holds or not, all Jena can do is check whether there are currently any counterexamples. If one were added later, you might have incorrect inferences.
Using the builtins available in the rule reasoner, you could do something with noValue and notEqual along the lines of:
#-- If an individual is disqualified by being
#-- connected to a something that is connected
#-- to something that is not equal to 1, then
#-- add a connectedToNonOne triple.
[rule1:
(?x p ?y), (?y v ?z), notEqual(?z,1)
->
(?x connectedToNonOne true)]
#-- Mark everything that is *not* disqualified
#-- with `q 'Yes'`.
[rule2:
noValue(?x, connectedToNonOne)
->
(?x q 'Yes')
I thought these two function were the same, but it seems that I was wrong.
I define two function f and g in this way:
let rec f n k =
match k with
|_ when (k < 0) || (k > n) -> 0
|_ when k = n -> 100
|_ -> (f n (k+1)) + 1
let rec g n k =
match k with
|_ when (k < 0) || (k > n) -> 0
| n -> 100
|_ -> (g n (k+1)) + 1
let x = f 10 5
let y = g 10 5
The results are:
val x : int = 105
val y : int = 100
Could anyone tell me what's the difference between these two functions?
EDIT
Why does it work here?
let f x =
match x with
| 1 -> 100
| 2 -> 200
|_ -> -1
List.map f [-1..3]
and we get
val f : x:int -> int
val it : int list = [-1; -1; 100; 200; -1]
The difference is that
match k with
...
when k = n -> 100
is a case that matches when some particular condition is true (k = n). The n used in the condition refers to the n that is bound as the function parameter. On the other hand
match k with
...
n -> 100
is a case that only needs to match k against a pattern variable n, which can always succeed. The n in the pattern isn't the same n as the n passed into the function.
For comparison, try the code
let rec g n k =
match k with
|_ when (k < 0) || (k > n) -> 0
| n -> n
|_ -> (g n (k+1)) + 1
and you should see that when you get to the second case, the value returned is the value of the pattern variable n, which has been bound to the value of k.
This behavior is described in the Variable Patterns section of the MSDN F# Language Reference, Pattern Matching:
Variable Patterns
The variable pattern assigns the value being matched to a variable
name, which is then available for use in the execution expression to
the right of the -> symbol. A variable pattern alone matches any
input, but variable patterns often appear within other patterns,
therefore enabling more complex structures such as tuples and arrays
to be decomposed into variables. The following example demonstrates a
variable pattern within a tuple pattern.
let function1 x =
match x with
| (var1, var2) when var1 > var2 -> printfn "%d is greater than %d" var1 var2
| (var1, var2) when var1 < var2 -> printfn "%d is less than %d" var1 var2
| (var1, var2) -> printfn "%d equals %d" var1 var2
function1 (1,2)
function1 (2, 1)
function1 (0, 0)
The use of when is described in more depth in Match Expressions.
The first function is ok, it calls recursively itself n-k times and returns 100 when matches with the conditional where k = n. So, it returns all the calls adding 1 n-k times. with your example, with n=10 and k=5 it is ok the result had been 105.
The problem is the second function. I tested here. See I changed the pattern n->100 to z->100 and it still matches there and never calls itself recursively. So, it always returns 100 if it does not fail in the first conditional. I think F# don't allow that kind of match so it is better to put a conditional to get what you want.
let rec f n =
match n with
| 0 | 1 | 2 -> 1
| _ -> f (n - 2) + f (n - 3)
Without CPS or Memoization, how could it be made tail recursive?
let f n = Seq.unfold (fun (x, y, z) -> Some(x, (y, z, x + y))) (1I, 1I, 1I)
|> Seq.nth n
Or even nicer:
let lambda (x, y, z) = x, (y, z, x + y)
let combinator = Seq.unfold (lambda >> Some) (1I, 1I, 1I)
let f n = combinator |> Seq.nth n
To get what's going on here, refer this snippet. It defines Fibonacci algorithm, and yours is very similar.
UPD There are three components here:
The lambda which gets i-th element;
The combinator which runs recursion over i; and
The wrapper that initiates the whole run and then picks up the value (from a triple, like in #Tomas' code).
You have asked for a tail-recursive code, and there are actually two ways for that: make your own combinator, like #Tomas did, or utilize the existing one, Seq.unfold, which is certainly tail-recursive. I preferred the second approach as I can split the entire code into a group of let statements.
The solution by #bytebuster is nice, but he does not explain how he created it, so it will only help if you're solving this specific problem. By the way, your formula looks a bit like Fibonacci (but not quite) which can be calculated analytically without any looping (even without looping hidden in Seq.unfold).
You started with the following function:
let rec f0 n =
match n with
| 0 | 1 | 2 -> 1
| _ -> f0 (n - 2) + f0 (n - 3)
The function calls f0 for arguments n - 2 and n - 3, so we need to know these values. The trick is to use dynamic programming (which can be done using memoization), but since you did not want to use memoization, we can write that by hand.
We can write f1 n which returns a three-element tuple with the current and two past values values of f0. This means f1 n = (f0 (n - 2), f0 (n - 1), f0 n):
let rec f1 n =
match n with
| 0 -> (0, 0, 1)
| 1 -> (0, 1, 1)
| 2 -> (1, 1, 1)
| _ ->
// Here we call `f1 (n - 1)` so we get values
// f0 (n - 3), f0 (n - 2), f0 (n - 1)
let fm3, fm2, fm1 = (f1 (n - 1))
(fm2, fm1, fm2 + fm3)
This function is not tail recurisve, but it only calls itself recursively once, which means that we can use the accumulator parameter pattern:
let f2 n =
let rec loop (fm3, fm2, fm1) n =
match n with
| 2 -> (fm3, fm2, fm1)
| _ -> loop (fm2, fm1, fm2 + fm3) (n - 1)
match n with
| 0 -> (0, 0, 1)
| 1 -> (0, 1, 1)
| n -> loop (1, 1, 1) n
We need to handle arguments 0 and 1 specially in the body of fc. For any other input, we start with initial three values (that is (f0 0, f0 1, f0 2) = (1, 1, 1)) and then loop n-times performing the given recursive step until we reach 2. The recursive loop function is what #bytebuster's solution implements using Seq.unfold.
So, there is a tail-recursive version of your function, but only because we could simply keep the past three values in a tuple. In general, this might not be possible if the code that calculates which previous values you need does something more complicated.
Better even than a tail recursive approach, you can take advantage of matrix multiplication to reduce any recurrence like that to a solution that uses O(log n) operations. I leave the proof of correctness as an exercise for the reader.
module NumericLiteralG =
let inline FromZero() = LanguagePrimitives.GenericZero
let inline FromOne() = LanguagePrimitives.GenericOne
// these operators keep the inferred types from getting out of hand
let inline ( + ) (x:^a) (y:^a) : ^a = x + y
let inline ( * ) (x:^a) (y:^a) : ^a = x * y
let inline dot (a,b,c) (d,e,f) = a*d+b*e+c*f
let trans ((a,b,c),(d,e,f),(g,h,i)) = (a,d,g),(b,e,h),(c,f,i)
let map f (x,y,z) = f x, f y, f z
type 'a triple = 'a * 'a * 'a
// 3x3 matrix type
type 'a Mat3 = Mat3 of 'a triple triple with
static member inline ( * )(Mat3 M, Mat3 N) =
let N' = trans N
map (fun x -> map (dot x) N') M
|> Mat3
static member inline get_One() = Mat3((1G,0G,0G),(0G,1G,0G),(0G,0G,1G))
static member (/)(Mat3 M, Mat3 N) = failwith "Needed for pown, but not supported"
let inline f n =
// use pown to get O(log n) time
let (Mat3((a,b,c),(_,_,_),(_,_,_))) = pown (Mat3 ((0G,1G,0G),(0G,0G,1G),(1G,1G,0G))) n
a + b + c
// this will take a while...
let bigResult : bigint = f 1000000
Here is the code that I am trying to get to work last line is where it is failing:
let rec gcd a b =
if b= 0 then
a
else
gcd b (a % b);;
let n = 8051
let mutable d = 0
let mutable c = 1
let mutable xi = 2
let mutable yi = 2
let f x = (pown x 2) + (c % n);;
while c < 100 do
while d = 1 do
xi <- (f xi)
yi <- (f(f(yi)))
printfn "%d%d" xi yi
d <- gcd(abs (xi - yi) n)
---------------------The Following Code works; Except for integer overflow on N---------
module Factorization
let rec gcd a b =
if b= 0 then
a
else
gcd b (a % b);;
let n = 600851475143N
let mutable d, c, xi, yi = 1, 1, 2, 2
let f x = (pown x 2) + (c % n);;
let maxN m =int(ceil(sqrt(float m)))
//if (n > maxN(xi)) && (n > maxN(yi)) then
while c < 100 do
d <- 1
while d = 1 do
if (maxN(n) > xi) && (maxN(n) > yi) then
xi <- f xi
yi <- f(f(yi))
d <- gcd (abs (xi - yi)) n
//fail
if d = n then d<-1
if d <> 1 then printfn "A prime factor of %d x = %d, y = %d, d = %d" n xi yi d
else
xi <- 2
yi <- 2
c <- c + 1;;
In addition to what #Rangoric pointed out, the outer brackets have to go as well otherwise currying won't work:
d <- gcd (abs(xi-yi)) n
Yikes, here are a few unsolicited tips (#BrokenGlass answered the question itself correctly).
First, you can assign all those mutables in one line:
let mutable d, c, xi, yi = 0, 1, 2, 2
Second, go easy on the parentheses:
xi <- f xi
yi <- f (f yi)
And of course, try to get rid of the mutables and while loops. But I'll leave that to you since I'm sure you are aware seeing that you implemented gcd using recursion.
Try:
d <- gcd (abs(xi-yi)) n
It is pointing out that abs is a int->int and not an int by itself. Wrapping it in parentheses causes the abs to be executed before gcd looks at it. This causes gcd to see the result of abs instead of abs itself.