I've been working on a task to create a function that returns the total number of smiley faces. Valid smiley faces look like: ":) :D ;-D :~)" and invalid smiling faces: ";( :> :} :] ".
So far this is how my answer looks:
def count_smileys(arr)
arr.to_s.count(":)", ":D", ";-D", ":~")
end
The only positive test my code returns:
Test Passed: Value == 0
Expected: 4, instead got: 0
Expected: 2, instead got: 0
Expected: 1, instead got: 0
What am I doing wrong and how can I fix it?
As the documentation for String#count says, each individual argument to String#count defines a set of characters, and the final set of characters to count is the intersection of all those sets.
In your case, the intersection is empty, therefore you are counting nothing:
:) is the set { :, ) }
:D is the set { :, D }
;-D is the set of characters starting with ; and ending with D, i.e. { ;, <, =, >, ?, #, A, B, C, D }
:~ is the set { :, ~ }
So, the intersection of all of those sets is
{ :, ) } ∩ { :, D } ∩ { ;, <, =, >, ?, #, A, B, C, D } ∩ { :, ~ }
= { : } ∩ { ;, <, =, >, ?, #, A, B, C, D } ∩ { :, ~ }
= ∅ ∩ { :, ~ }
= ∅
i.e. the empty set.
Very good answer by Jörg.
To also provide a possible solution. You don't need to cast this to a string, as array also has a count method which accepts a block.
def count_smileys(arr)
array.count do |element|
[":)", ":D", ";-D", ":~"].include?(element)
end
end
https://makandracards.com/makandra/31141-ruby-counting-occurrences-of-an-item-in-an-array-enumerable
[A,B,C|_] = [1,2,3,4,5,6,7]
A = 1
B = 2
C = 3.
I expected this result. However, when I have:
L = [A,B,C,D]
how to do:
L = [1,2,3,4,5,6,7]
A = 1
B = 2
C = 3
D = 4
?
The problem is that I don't know how long is L. Only thing that I know: L is shorter than rightside list and L contains only variables.
We just "insert the free variable" at the variables list's tail, append(Vars, _, ExtendedList), and then pattern match, ExtendedList = Data. Contracting, we get:
match_vars(Vars, Data):-
append(Vars, _, Data).
Testing:
2 ?- match_vars([A,B],[1,2,3,4,5]).
A = 1,
B = 2.
3 ?- match_vars([A,B,C,D],[1,2,3,4,5]).
A = 1,
B = 2,
C = 3,
D = 4.
4 ?-
(using append/3 was already mentioned in the comments).
Suppose I have an original string and an encoded string , like the following:
"abcd" -> "0010111111001010", then one possible solution would be that "a" matches with "0010", "b" matches with "1111", "c" matches with "1100", "d" matches with "1010".
How to write a program, that given these two strings, and figure out possible encoding rules?
My first scratch looks like this:
fun partition(orgl, encode) =
let
val part = size(orgl)
fun porpt(str, i, len) =
if i = len - 1 then
[substring(str, len * (len - 1), size(str) - (len - 1) * len)]
else
substring(str, len * i, len)::porpt(str, i + 1, len)
in
porpt(encode, 0, part)
end;
But obviously it can not check whether the two substrings match the identical character, and there are many other possibilities other than proportionally partitioning the strings.
What should be the appropriate algorithms for this problem?
P.S. Only prefix code is allowed.
What I have learned has not really got into serious algorithms yet, but I did some searching about backtracking and wrote my second version of the code:
fun partition(orgl, encode) =
let
val part = size(orgl)
fun backtrack(str, s, len, count, code) =
let
val current =
if count = 1 then
code#[substring(str, s, size(str) - s)]
else
code#[substring(str, s, len)]
in
if len > size(str) - s then []
else
if proper_prefix(0, orgl, code) then
if count = 1 then current
else
backtrack(str, s + len, len, count - 1, current)
else
backtrack(str, s, len + 1, count, code)
end
in
backtrack(encode, 0, 1, part, [])
end;
Where the function proper_prefix would check prefix code and unique mapping. However, this function does not function correctly.
For example, when I input :
partition("abcd", "001111110101101");
The returned result is:
uncaught exception Subscript
FYI, the body of proper_prefix looks like this:
fun proper_prefix(i, orgl, nil) = true
| proper_prefix(i, orgl, x::xs) =
let
fun check(j, str, nil) = true
| check(j, str, x::xs) =
if String.isPrefix str x then
if str = x andalso substring(orgl, i, 1) = substring(orgl, i + j + 1, 1) then
check(j + 1, str, xs)
else
false
else
check(j + 1, str, xs)
in
if check(0, x, xs) then proper_prefix(i + 1, orgl, xs)
else false
end;
I'd try a back-tracking approach:
Start with an empty hypothesis (i.e. set all encodings to unknown). Then process the encoded string character by character.
At every new code character, you have two options: Either append the code character to the encoding of the current source character or go to the next source character. If you encounter a source character that you already have an encoding for, check if it matches and go on. Or if it doesn't match, go back and try another option. You can also check the prefix-property during this traversal.
Your example input could be processed as follows:
Assume 'a' == '0'
Go to next source character
Assume 'b' == '0'
Violation of prefix property, go back
Assume 'a' == '00'
Go to next source character
Assume 'b' == '1'
...
This explores the range of all possible encodings. You can either return the first encoding found or all possible encodings.
If one were to naively iterate all possible translations of abcd → 0010111111001010, this possibly leads to a blow-up. Simple iteration also appears to lead to a lot of invalid translations one would have to skip:
(a, b, c, d) → (0, 0, 1, 0111111001010) is invalid because a = b
(a, b, c, d) → (0, 0, 10, 111111001010) is invalid because a = b
(a, b, c, d) → (0, 01, 0, 111111001010) is invalid because a = c
(a, b, c, d) → (00, 1, 0, 111111001010) is one possibility
(a, b, c, d) → (0, 0, 101, 11111001010) is invalid because a = b
(a, b, c, d) → (0, 010, 1, 11111001010) is another possibility
(a, b, c, d) → (001, 0, 1, 11111001010) is another possibility
(a, b, c, d) → (0, 01, 01, 11111001010) is invalid because b = c
(a, b, c, d) → (00, 1, 01, 11111001010) is another possibility
(a, b, c, d) → (00, 10, 1, 11111001010) is another possibility
...
If all character strings contain each character exactly once, then this blow-up of results is the answer. If the same character occurs more than once, this further constrains the solution. E.g. matching abca → 111011 could generate
(a, b, c, a) → (1, 1, 1, 011) is invalid because a = b = c, a ≠ a
(a, b, c, a) → (1, 1, 10, 11) is invalid because a = b, a ≠ a
(a, b, c, a) → (1, 11, 0, 11) is invalid because a = b, a ≠ a
(a, b, c, a) → (11, 1, 0, 11) is one possibility
... (all remaining combinations would eventually prove invalid)
For a given hypothesis, you can choose the order in which to verify your constraints. Either
See if any mappings overlap. (I think this is what Nico calls the prefix property.)
See if any character that occurs more than once actually occurs in both places in the bit string.
An algorithm using this search strategy will have to find an order of checking constraints in order to try to a hypothesis as soon possible. My intuition tells me that a constraint a → β is worth investigating sooner if the bit string β is long and if it occurs many times.
Another strategy is ruling out that a particular character can map to any bit string of/above/below a certain length. For example, aaab → 1111110 rules out a mapping to any bit string of length above 2, and abcab → 1011101 rules out a mapping to any bit string of length different than 2.
For the programming part, try and think of ways to represent hypotheses. E.g.
(* For the hypothesis (a, b, c, a) → (11, 1, 0, 11) *)
(* Order signifies first occurrence *)
val someHyp1 = ([(#"a", 2), (#"b", 1), (#"c", 1)], "abca", "111011")
(* Somehow recurse over hypothesis and accumulate offsets for each character, e.g. *)
val someHyp2 = ([(#"a", 2), (#"b", 1), (#"c", 1)],
[(#"a", 0), (#"b", 2), (#"c", 3), (#"a", 4)])
And make a function that generates new hypotheses in some order, and a function that finds if a hypothesis is valid.
fun nextHypothesis (hyp, origStr, encStr) = ... (* should probably return SOME/NONE *)
fun validHypothesis (hyp, origStr, encStr) =
allStr (fn (i, c) => (* is bit string for c at its
accumulated offset in encStr? *)) origStr
(* Helper function that checks whether a predicate is true for each
character in a string. The predicate function takes both the index
and the character as argument. *)
and allStr p s =
let val len = size s
fun loop i = i >= len orelse p (i, String.sub (s, i)) andalso loop (i+1)
in loop 0 end
An improvement over this framework would be to change the order in which to explore hypotheses, since some search paths can rule out larger amounts of invalid mappings than others.
So basically here is some Prolog code I wrote, using GNU-Prolog 1.4.4.
A is 1,
B = (A == 2),
B == no.
A is 2,
B = (A == 2),
B == no.
What I am expecting is when A is 2, then B == no returns no, when A is 1, then B == no returns yes.
However, to my surprise, both two code snippets return no, which leaving me the impression that B == no works in an unexpected way..
So basically how can I write the code in the way I want?
Could anyone give me some help?
The line
B = (A == 2)
does not compute A==2 in any way and assign the result to B. It just unifies the term B (a variable) with the term (A==2). The result of the unification is that B is now A==2. You can check yourself by omitting B==no:
?- A is 1, B=(A==2).
A = 1,
B = (1==2) ?
yes
If you really want that B unifies with the atoms yes resp. no you can use an if-then-else construct:
( A == 2 -> B = yes
; otherwise -> B = no)