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
Related
I have this google sheets input table
How to flip the range A2:E range horizontally with Arrayformula because the range A1:E is growing.
Input Output
c a t t a c
b i r d d r i b
h o r s e e s r o h
t i g e r r e g i t
The old way
=TRANSPOSE(SORT(TRANSPOSE(A2:E),SEQUENCE(ROWS(
TRANSPOSE(A2:E))),0))
The new way
=LAMBDA(range,
TRANSPOSE(SORT(range,SEQUENCE(ROWS(range)),0)))(TRANSPOSE(A2:E))
Used formulas help
TRANSPOSE - SORT - SEQUENCE - ROWS - LAMBDA
I have an array in Ruby
words = ["horses", "follow", "useful", "offset"]
Reference:
h o r s e s
f o l l o w
u s e f u l
o f f s e t
I want to get a list of all its diagonals like this.
Here is want I expect in result:
["o", "uf", "fsf", "hoes", "olfe", "rlut", "sol", "ew", "s"]
Would be helpful if anyone can help me a bit on this. Thanks
Try that:
words = ["horses", "follow", "useful", "offset"]
words.reverse.each_with_index.map{|s,i| " " * i + s }.inject(Array.new(words.size + words.last.size-1,"")) do |a,s|
s.chars.each_with_index do |c,i|
a[i] = c + a[i]
end
a
end.map(&:strip)
# => ["o", "uf", "fsf", "hoes", "olfe", "rlut", "sol", "ew", "s"]
At first words.reverse.each_with_index.map{|s,i| " " * i + s } builds array with whitespace offset:
offset
useful
follow
horses
Inject creates array of empty strings and inside main block each string chars are prepended to proper array element
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.
I have a question for the Follow sets of the following rules:
L -> CL'
L' -> epsilon
| ; L
C -> id:=G
|if GC
|begin L end
I have computed that the Follow(L) is in the Follow(L'). Also Follow(L') is in the Follow(L) so they both will contain: {end, $}. However, as L' is Nullable will the Follow(L) contain also the Follow(C)?
I have computed that the Follow(C) = First(L') and also Follow(C) subset Follow(L) = { ; $ end}.
In the answer the Follow(L) and Follow(L') contain only {end, $}, but shouldn't it contain ; as well from the Follow(C) as L' can be null?
Thanks
However, as L' is Nullable will the Follow(L) contain also the Follow(C)?
The opposite. Follow(C) will contain Follow(L). Think of the following sentence:
...Lx...
where X is some terminal and thus is in Follow(L). This could be expanded to:
...CL'x...
and further to:
...Cx...
So what follows L, can also follow C. The opposite is not necessarily true.
To calculate follows, think of a graph, where the nodes are (NT, n) which means non-terminal NT with the length of tokens as follow (in LL(1), n is either 1 or 0). The graph for yours would look like this:
_______
|/_ \
(L, 1)----->(L', 1) _(C, 1)
| \__________|____________/| |
| | |
| | |
| _______ | |
V |/_ \ V V
(L, 0)----->(L', 0) _(C, 0)
\_______________________/|
Where (X, n)--->(Y, m) means the follows of length n of X, depend on follows of length m of Y (of course, m <= n). That is to calculate (X, n), first you should calculate (Y, m), and then you should look at every rule that contains X on the right hand side and Y on the left hand side e.g.:
Y -> ... X REST
take what REST expands to with length n - m for every m in [0, n) and then concat every result with every follow from the (Y, m) set. You can calculate what REST expands to while calculating the firsts of REST, simply by holding a flag saying whether REST completely expands to that first, or partially. Furthermore, add firsts of REST with length n as follows of X too. For example:
S -> A a b c
A -> B C d
C -> epsilon | e | f g h i
Then to find follows of B with length 3 (which are e d a, d a b and f g h), we look at the rule:
A -> B C d
and we take the sentence C d, and look at what it can produce:
"C d" with length 0 (complete):
"C d" with length 1 (complete):
d
"C d" with length 2 (complete):
e d
"C d" with length 3 (complete or not):
f g h
Now we take these and merge with follow(A, m):
follow(A, 0):
epsilon
follow(A, 1):
a
follow(A, 2):
a b
follow(A, 3):
a b c
"C d" with length 0 (complete) concat follow(A, 3):
"C d" with length 1 (complete) concat follow(A, 2):
d a b
"C d" with length 2 (complete) concat follow(A, 1):
e d a
"C d" with length 3 (complete or not) concat follow(A, 0) (Note: follow(X, 0) is always epsilon):
f g h
Which is the set we were looking for. So in short, the algorithm becomes:
Create the graph of follow dependencies
Find the connected components and create a DAG out of it.
Traverse the DAG from the end (from the nodes that don't have any dependency) and calculate the follows with the algorithm above, having calculated firsts beforehand.
It's worth noting that the above algorithm is for any LL(K). For LL(1), the situation is much simpler.
function expandVars(tmpl,t)
return (tmpl:gsub('%$([%a ][%w ]+)', t)) end
local sentence = expandVars("The $adj $char1 looks at you and says, $name, you are $result", {adj="glorious", name="Jayant", result="the Overlord", char1="King"})
print(sentence)
The above code work only when I have ',' after the variable name like, in above sentence it work for $ name and $ result but not for $adj and $char1, Why is that ?
Problem:
Your pattern [%a ][%w ]+ means a letter or space, followed by at least one letter or number or space. Since regexp is greedy, it will try to match as large a sequence as possible, and the match will include the space:
function expandVars(tmpl,t)
return string.gsub(tmpl, '%$([%a ][%w ]+)', t)
end
local sentence = expandVars(
"$a1 $b and c $d e f ",
{["a1 "]="(match is 'a1 ')", ["b and c "]="(match is 'b and c ')", ["d e f "]="(match is 'd e f ')", }
)
This prints
(match is 'a1 ')(match is 'b and c ')(match is 'd e f ')
Solution:
The variable names must match keys from your table; you could accepts keys that have spaces and all sort of characters but then you are forcing the user to use [] in the table keys, as done above, this is not very nice :)
Better keep it to alphanumeric and underscore, with the constraint that it cannot start with a number. This means to be generic you want a letter (%a), followed by any number of (including none) (* rather than +) of alphanumeric and underscore [%w_]:
function expandVars(tmpl,t)
return string.gsub(tmpl, '%$(%a[%w_]*)', t)
end
local sentence = expandVars(
"$a $b1 and c $d_2 e f ",
{a="(match is 'a')", b1="(match is 'b1')", d_2="(match is 'd_2')", }
)
print(sentence)
This prints
(match is 'a') (match is 'b1') and c (match is 'd_2') e f; non-matchable: $_a $1a b
which shows how the leading underscore and leading digit were not accepted.