Operator and operand don't agree ML - ml

I'm working on a function for class, and I am getting this error.
Error: operator and operand don't agree [tycon mismatch]
operator domain: 'Z list
operand: 'Y list -> 'Y list
in expression:
null tl
fun removedub(L) =
if (null L) then nil
else if (null tl(L)) then hd(L)
else if hd(L) = hd(tl(L)) then removedub(tl(L))
else hd(L) :: removedub(tl(L));
val list = ["a", "a", "b", "b", "c"];
removedub(list);
I'm not sure how to fix this, or really what is causing it, any tips?

You set the parentheses wrong. When you write
null tl(L)
then that has the same meaning as
null(tl)(L)
However, you want
null(tl(L))

Related

How can I make an array true or false?

On Code.org, I'm trying to make a quiz that picks an answer based on what the user has placed in the array. However, regardless of what is in the array it always comes out false.
I've tried changing the statement to have more than one equal sign, I've tried doing it backward and making the if statement if list !== [list] and I've tried removing the quotations. Nothing has worked. I've also tried defining the correctlist variable inside the if statement, but that still produces false.
var mylist = ["a". "b", "c"];
var correctlist;
if (mylist == ["a", "b", "c"]) {
correctlist = true;
} else {
correctlist = false;
}
console.log(correctlist);
It always comes out as false.
I expected the console log to state true but it always says false.
You will notice that:["a", "b", "c"] == ["a", "b", "c"]
always returns false.
That is because these are two different arrays. Just because the elements string match, the arrays are not the same.
You will either need to iterate through the elements to compare each, convert them to something that can be compared through a plain equality, or use a library with a "deep" equals.
JSON.stringify(["a", "b", "c"]) == JSON.stringify(["a", "b", "c"])

Need a `values_at_if ` method to map values in ruby

I have two arrays of the same size
response = ["N","N","Y","Y","Y"]
mapping = ["A","B","C","D","E"]
I need to select the elements in mapping whose corresponding value in response, i.e., the element with the same index, is "Y", as below
["C","D","E"]
It reminds me of the values_at method. My solution is as follows
def values_at_if(response, mapping)
result=[]
response.each_index |k|
if k=="Y"
result << mapping[k]
end
end
result
end
I am not happy with it. Please let me know of a way to do it efficiently.
Update
The simplest solution I can come up with is:
mapping.select.with_index {|_,i| response[i] == "Y"}
#=>["C", "D", "E"]
This will select all the elements in mapping where the corresponding index in response equals "Y"
TL;DR Other options include:
mapping.values_at(*response.each_with_index.select {|v,_| v == "Y"}.map(&:last))
mapping.zip(response).map {|k,v| k if v == "Y"}.compact
The first uses each with index which will be
[["N",0],["N",1],["Y",2],["Y",3],["Y",4]]
then we select the groups where the first element is "Y" and map the indexes to pass to values_at
The second version zips the mapping and the response together creating.
[["A", "N"], ["B", "N"], ["C", "Y"], ["D", "Y"], ["E", "Y"]]
Then map the first element only when the second element is "Y". the compact removes the nil values from the mapping.
There are a lot of other ways to accomplish this task if you have a look through the Enumerable module
I would go with
mapping.zip(response).select { |_, r| r == 'Y' }.map(&:first)
#=> ["C", "D", "E"]
Convert response to an Enumerator; each without a block does that. Then use it in the select block. If the block returns true then the item is selected:
response = ["N","N","Y","Y","Y"]
mapping = ["A","B","C","D","E"]
enum_resp = response.each
mapping.select{ enum_resp.next == "Y" } # =>["C", "D", "E"]
Note it would save memory if response would consist of false and trues, which also would make the comparison in the select block unnecessary.
response.each_with_object([]).with_index do |(v, arr), i|
arr << mapping[i] if v == 'Y'
end
Or
mapping.each_with_object([]).with_index do |(v, arr), i|
arr << v if response[i] == 'Y'
end

How can I test that some specific element comes before another specific element in an array?

I had a problem whereby a list of jobs, each represented by a character "a", "b", "c" etc, had to be sorted given that some of them depended on other jobs. So if job "a" depended on "b", and "b" and "c" didn't depend on any job, the list 'abc' would be sorted as 'bac', simple.
My problem is I want to write a test to check that jobs come after the jobs they depend on in the output array.
Example
If job "c" depends on job "f", how can I test that "f" is before "c" in
array = ["a", "b", "f", "c", "d", "e"]
There is already most of the solution in the comment by Cary Swoveland. Here is a full example which takes care of all the cases (no c, no f, neither, wrong order, ok)
jobs = %w[a b f c d e]
index_c = jobs.index('c')
index_f = jobs.index('f')
if index_c && index_f && index_c > index_f
puts "Everything is fine"
elsif index_c && index_f
puts "job c is before job f"
elsif !index_c && !index_f
puts "jobs are missing"
elsif !index_c
puts "no job c"
else
puts "no job f"
end
You could create a hash with the job and its dependency, for instance and as in your example if job c depends on f and b depends on a, then:
hash = {c: 'f', b: 'a'}
So, over your hash you can use map to get a "plain" array where you check if the index of the hash value in your array is minor than the index of the hash key (to string) also in the array, if so, then you add true, then checking for all values within the array, all must be true:
array = ['a', 'b', 'f', 'c', 'd', 'e']
result = hash.map{|k,v| array.index(v) < array.index(k.to_s)}
p result.all?{|e| e} # => true
So, using Minitest, you can test result.all?{|e| e}.eql? is equal to true:
require 'minitest/autorun'
class Test < Minitest::Test
def test_a_job_is_before_its_dependency
hash = {c: 'f', b: 'a'}
array = ['a', 'b', 'f', 'c', 'd', 'e']
result = hash.map{|k,v| array.index(v) < array.index(k.to_s)}.all?{|e| e}
assert result.equal? true
end
end
The best data format for this problem would be a dependency graph or a directed acyclic graph.
To get a suitable array of jobs, you'd need topological sorting, e.g. using Kahn's algorithm or a depth-first search.
Plexus gem offers a topological sort.
require 'plexus'
include Plexus
dg = Digraph["a","b", "a","f", "f","c", "f","d", "d","e", "b","f"]
p dg.topsort
# ["a", "b", "f", "d", "e", "c"]
require 'plexus/dot'
dg.write_to_graphic_file('png','visualize')
All you need to check is if the resulting array is empty or not:
require 'plexus'
include Plexus
dg = Digraph["c","a", "a","b", "b","a"]
p dg.topsort
# []
If it's empty, there's at least one cycle in your dependencies, and no array can be found. If the array's not empty, it includes every element in a correct order. No need to check it further.

Looping over a map in haskell

import Data.Foldable (for_)
import Data.Map (Map,toList)
m :: Map String String
m = [("a","1"),("b","2")]
main =
for_ (toList m) $ \(q,a) ->
do putStrLn q
x <- getLine
putStrLn (if x == a
then "Yes"
else "No: " ++ a)
I get the error:-
foo.hs:5:5: error:
* Couldn't match expected type `Map String String'
with actual type `[([Char], [Char])]'
* In the expression: [("a", "1"), ("b", "2")]
In an equation for `m': m = [("a", "1"), ("b", "2")]
Failed, modules loaded: none.
Thanks for your help. I was interested in the for_i solution , but I cannot load Control.Lens
You have taken the code from this answer to a previous question, but omitted the first line:
{-# LANGUAGE OverloadedLists #-}
Don't omit the first line.
Map String String is not just an alias for lists of tuples; it is a distinct data type, and so your assignment does not type-check. You need to use the function Data.Map.fromList to convert your list to a proper Map k v value.
m = Data.Map.fromList [("a","1"),("b","2")]

Custom Sort Groovy JSONArray - Custom Values First, Then Alphabetical

I have a static list of values that is in a JSONArray. Here is my example array:
JSONArray json = new JSONArray()
json = ["B", "E", "C", "Z", "A", "X", "F", "H"]
I need to sort this json array in a custom way. I need to put "E" first, "F" second, and then sort the rest by alphabetical order.
I want my end result to be this:
json = ["E", "F", "A", "B", "C", "H", X", "Z"]
Groovy has the basic sort functionality that I can sort alphabetically or reverse alphabetically using:
json.sort()
or
json.reverse()
I'm looking for an easy way to do a custom sort.
in my 5-min experiment I used weights:
def json = ["B", "E", "C", "Z", "A", "X", "F", "H"]
def weights = [ E:10, F:9 ]
json.sort{
it.charAt( 0 ) - ( weights[ it ] ?: 0 )
}
assert '[E, F, A, B, C, H, X, Z]' == json.toString()
you might want to include some error checking
You can use closures if you define your own sort method, but what you're actually asking for is some array splitting with a little normal sorting.
json.findAll{it = 'E'} + json.findAll{it = 'F'} + json.findAll{!(it in ['E', 'F'])}.sort()
If you're worried about the efficiency of looping through your json 3 times you can iterate through your json once, adding it to different arrays as you go.
The below example is a little fancier. The inject method will iterate over a collection, passing a value between each iteration (in our case a list of 3 lists. The first list will hold our E's, the second our F's, and the 3rd for everything else. After sorting our catchall list we use .flatten() to transform the 3 lists back into one list.
List organizedList = json.inject([[],[],[]]) {List<List> result, String jsonValue ->
select(jsonValue) {
case 'E':
result.get(0).add(jsonValue) // Could have just added 'E' but I like symmetry
break;
case 'F':
result.get(1).add(jsonValue)
break;
default:
result.get(2).add(jsonValue)
}
return result // Gets passed to each iteration over json
}
organizedList.get(2).sort() // sort on a list modifies the original list
organizedList.flatten()
It's also possible using sort with a closure where you define your own sorting; but as you can see, it doesn't flow quite as easily.
json.sort {String a, String b ->
if (a = b) return 0 // For efficiency's sake
def letterFirst = {String priority -> // Closure to help sort against a hardcoded value
if (a = priority) return 1
if (b = priority) return -1
return 0
}
def toReturn = letterFirst('E')
if (!toReturn) toReturn = letterFirst('F') // groovy evaluates 0 as false
if (!toReturn) toReturn = a <=> b
return toReturn
}

Resources