Haskell - infinite list - - list

I have this data and types:
data Cliente = Uncliente {nombre::String,resistencia::Int,bebidas::[Bebida],amigos::[Cliente]} deriving (Show)
type Bebida = Cliente -> Cliente
type Nombre = String
type Duracion = Float
type Acciones = [Bebida]
type Itinerario = (Nombre,Duracion,Acciones)
And I have this slogan:
"Define chuckNorris, who is a customer who was initially called "Chuck", has resistance 1000, is Ana's friend and took all sodas that exist in the universe, starting with a level 1 soda, then a level 2 soda, and So on."
and i do:
chuckNorris = Uncliente {
nombre = "Chuck",
resistencia = 1000,
bebidas = [soda 1,2..],
amigos = [ana]
But this does not work because the infinite list of drinks is not like that
How would you write the infinite list?
like soda 1, soda 2, soda 3 ........

I'd write it as map soda [1,2..]
map effectively takes each element in the list (1, 2, 3 and so on) and applies soda to it, resulting in another list with soda 1, soda 2, soda 3 and so on.

The way to do this is via the map function. Infinite lists which step by 1 can be done with the .. syntax.
map soda [1..]
This is semantically equivalent to something like
[soda 1, soda 2, soda 3, {- and so on... -}]
The reason this works is thanks to Haskell's lazy evaluation. The calls to soda only occur once you start traversing the infinite list, so no need to fear getting caught in an infinite loop here.

Related

Calculating the value of a field based on the difference between the values of another field in two adjacent positions using haskell

I have a list of custom data objects which track an increasing total value on a daily basis using one field total. Another field in the custom data type is the value new. Using a csv file I have read in the values for date and total and am trying to calculate and set the values for new from these values.
data item = Item{
date :: Day,
total :: Int,
new :: Int
}
Before
date
total
new
01/01/2021
0
0
02/01/2021
2
0
03/01/2021
6
0
04/01/2021
15
0
After
date
total
new
01/01/2021
0
0
02/01/2021
2
2
03/01/2021
6
4
04/01/2021
15
9
My understanding is that in haskell I should be trying to avoid the use of for loops which iterate over a list until the final row is reached, for example using a loop control which terminates upon reaching a value equal to the length of the list.
Instead I have tried to create a function which assigns the value of new which can used with map to update each item in the list. My problem is that such a function requires access to both the item being updated, as well as the previous item's value for total and I'm unsure how to implement this in haskell.
--Set daily values by mapping single update function across list
calcNew:: [Item] -> Int -> [Item]
calcNew items = map updateOneItem items
-- takes an item and a value to fill the new field
updateOneItem :: Item -> Int -> Item
updateOneItem item x = Item date item total item x
Is it possible to populate that value while using map? If not, is a recursive solution required?
We can do this by zipping the input list with itself, shifted by one step.
Assuming you have a list of items already populated with total values, which you want to update to contain the correct new values (building an updated copy of course),
type Day = Int
data Item = Item{ -- data Item, NB
date :: Day,
total :: Int,
new :: Int
} deriving Show
calcNews :: [Item] -> [Item]
calcNews [] = []
calcNews totalsOK#(t:ts) = t : zipWith f ts totalsOK
where
f this prev = this{ new = total this - total prev }
This gives us
> calcNews [Item 1 0 0, Item 2 2 0, Item 3 5 0, Item 4 10 0]
[Item {date = 1, total = 0, new = 0},Item {date = 2, total = 2, new = 2},
Item {date = 3, total = 5,new = 3},Item {date = 4, total = 10, new = 5}]
Of course zipWith f x y == map (\(a,b) -> f a b) $ zip x y, as we saw in your previous question, so zipWith is like a binary map.
Sometimes (though not here) we might need access to the previously calculated value as well, to calculate the next value. To arrange for that we can create the result by zipping the input with the shifted version of the result itself:
calcNews2 :: [Item] -> [Item]
calcNews2 [] = []
calcNews2 (t:totalsOK) = newsOK
where
newsOK = t : zipWith f totalsOK newsOK
f tot nw = tot{ new = total tot - total nw }

Converting a list to a map in Scala

I want to create a simple program that calculates someone's age after x years. so first you assign someone's current age to a variable, and then I want to use map to display the future ages.
What I have so far is:
val age = 18
val myList = (1 to 2000).toList
Basically, I want the numbers from the list and make it a map key. And for the value, it's a sum of variable and key. so the map would look like this:
1 -> 19, 2 -> 20, 3 -> 21......
How can I accomplish this?
Consider mapping to tuples
val age = 18
val ageBy: Map[Int, Int] = (1 to 2000).map(i => i -> (age + i)).toMap
ageBy(24) // res1: Int = 42

How to use for loop in list in python 3?

I have a question about writing for loops in python 3.
Basically, I don't understand how to write for loop if I have a list that contains two elements, like this one:
list1 = [("Berlin", 22), ("Zagreb", 30), ("New York", 25), ("Chicago", 20), ("Paris", 29)]
This is basically a list that contains cities and their temperatures in Celsius degrees, and I would like to create a new list that contains cities but now their temperature in Fahrenheit. The formula is:
F° = (9/5)*C° + 32
I don't understand how am I suppose to loop through this list that contains two elements in every member.
Use a list comprehension:
list1 = [("Berlin", 22), ("Zagreb", 30), ("New York", 25), ("Chicago", 20), ("Paris", 29)]
list2 = [(city, 9/5 * temp + 32) for city, temp in list1]
print(list2)
# [('Berlin', 71.599999999999994), ('Zagreb', 86.0), ('New York', 77.0), ('Chicago', 68.0), ('Paris', 84.200000000000003)]
Here, you iterate through list of tuples getting city names to city and temperature in Celsius to temp and convert Celsius to Farenheit.
Without list comprehension:
list2 = []
for city, temp in list1:
list2.append((city, 9/5 * temp + 32))
print(list2)
# [('Berlin', 71.599999999999994), ('Zagreb', 86.0), ('New York', 77.0), ('Chicago', 68.0), ('Paris', 84.200000000000003)]
First thing you need to know is to access elements in a 2D list. According to your list1, city is in the 0th position and temperature is in 1st position in a row. Within a simple for loop, you can access those as follows. Remember to keep the indentation, to specify the body of the for loop.
for element in list1:
city = element[0]
temp_c = element[1]
Then you can directly use temp_c to compute temperature in Fahrenheit (temp_f), within the loop.
temp_f = (9 / 5) * temp_c + 32
Next task is to append calculated temp_f values to a new list (list2) along with city name.
list2.append((city, temp_f))
But before that you should define the list2. (somewhere near you define list1)
list2 =[]
So it's done. You can check it works using a print statement.
for element in list2:
print(element)
This code can be implemented much shorter.
I expand it to reduce the complexity. Hope you got it.

creating a list from a discrete function in mathematica

I'm trying to make a list of lists {{a},{b}...}, but instead I'm building a list of non-list terms {{{a}},{{b}}...}
First, I started with a discrete function:
f[n_]:=RandomReal[BinormalDistribution[{c[[n, 3]], c[[n, 1]]}, ...........
Second, I made a list of lists by:
d = Array[f, 100]
Outputs: {{{1.64219, 0.0231185}}, {{0.690885, 0.00599381}},......
Which can not be read by SmoothDensityHistogram:
SmoothDensityHistogram::ldata: {{1.64219,0.0231185}} is not a valid dataset or list of datasets.
You can Flatten a single level in your list of lists. Essentialy you're squeezing out a singleton dimension in your 3d array, making it 2d:
In[22]:= mylist = {{{1.64219, 0.0231185}}, {{0.690885, 0.00599381}}}
Out[22]= {{{1.64219, 0.0231185}}, {{0.690885, 0.00599381}}}
In[23]:= Dimensions[mylist]
Out[23]= {2, 1, 2}
In[24]:= mymatrix = Flatten[mylist, 1]
Out[24]= {{1.64219, 0.0231185}, {0.690885, 0.00599381}}
In[25]:= Dimensions[mymatrix]
Out[25]= {2, 2}

difflib.get_close_matches GET SCORE

I am trying to get the score of the best match using difflib.get_close_matches:
import difflib
best_match = difflib.get_close_matches(str,str_list,1)[0]
I know of the option to add 'cutoff' parameter, but couldn't find out how to get the actual score after setting the threshold.
Am I missing something? Is there a better solution to match unicode strings?
I found that difflib.get_close_matches is the simplest way for matching/fuzzy-matching strings. But there are a few other more advanced libraries like fuzzywuzzy as you mentioned in the comments.
But if you want to use difflib, you can use difflib.SequenceMatcher to get the score as follows:
import difflib
my_str = 'apple'
str_list = ['ape' , 'fjsdf', 'aerewtg', 'dgyow', 'paepd']
best_match = difflib.get_close_matches(my_str,str_list,1)[0]
score = difflib.SequenceMatcher(None, my_str, best_match).ratio()
In this example, the best match between 'apple' and the list is 'ape' and the score is 0.75.
You can also loop through the list and compute all the scores to check:
for word in str_list:
print "score for: " + my_str + " vs. " + word + " = " + str(difflib.SequenceMatcher(None, my_str, word).ratio())
For this example, you get the following:
score for: apple vs. ape = 0.75
score for: apple vs. fjsdf = 0.0
score for: apple vs. aerewtg = 0.333333333333
score for: apple vs. dgyow = 0.0
score for: apple vs. paepd = 0.4
Documentation for difflib can be found here: https://docs.python.org/2/library/difflib.html
To answer the question, the usual route would be to obtain the comparative score for a match returned by get_close_matches() individually in this manner:
match_ratio = difflib.SequenceMatcher(None, 'aple', 'apple').ratio()
Here's a way that increases speed in my case by about 10% ...
I'm using get_close_matches() for spellcheck, it runs SequenceMatcher() under the hood but strips the scores returning just a list of matching strings. Normally.
But with a small change in Lib/difflib.py currently around line 736 the return can be a dictionary with scores as values, thus no need to run SequenceMatcher again on each list item to obtain their score ratios. In the examples I've shortened the output float values for clarity (like 0.8888888888888888 to 0.889). Input n=7 says to limit the return items to 7 if there are more than 7, i.e. the highest 7, and that could apply if candidates are many.
Current mere list return
In this example result would normally be like ['apple', 'staple', 'able', 'lapel']
... at the default cutoff of .6 if omitted (as in Ben's answer, no judgement).
The change
in difflib.py is simple (this line to the right shows the original):
return {v: k for (k, v) in result} # hack to return dict with scores instead of list, original was ... [x for score, x in result]
New dictionary return
includes scores like {'apple': 0.889, 'staple': 0.8, 'able': 0.75, 'lapel': 0.667}
>>> to_match = 'aple'
>>> candidates = ['lapel', 'staple', 'zoo', 'able', 'apple', 'appealing']
Increasing minimum score cutoff/threshold from .4 to .8:
>>> difflib.get_close_matches(to_match, candidates, n=7, cutoff=.4)
{'apple': 0.889, 'staple': 0.8, 'able': 0.75, 'lapel': 0.667, 'appealing': 0.461}
>>> difflib.get_close_matches(to_match, candidates, n=7, cutoff=.7)
{'apple': 0.889, 'staple': 0.8, 'able': 0.75}
>>> difflib.get_close_matches(to_match, candidates, n=7, cutoff=.8)
{'apple': 0.889, 'staple': 0.8}