I do not understand it well about Reduction in Haskell in this Function:
removeone :: Eq a = > a -> [ a ] -> [ a ]
removeone _ [] = []
removeone x ( y : ys )
| x == y = removeone x ys
| otherwise = y : ( removeone x ys )
remdups :: Eq a = > [ a ] -> [ a ]
remdups [] = []
remdups ( x : xs ) = x : remdups ( removeone x xs )
How could I use this function to explain Reduction steps in a List (for example remdups [3,7,3,7,5,7])?
Start by remdups [3,7,3,7,5,7] and simplify the expression as to the left as possible. Remember that [x,y,z] is a shorthand for x:y:z:[]. Hence remdups (3:7:....) = 3 : remdups (removeone 3 (7:....)) = ... and now youl need to use the definition of removeone since no equation of remdups applies. After removeone generates a : or [], you will return to simplifying the remdups call.
One row is one reduction. In the comments are row numbers with reduction codes. My example uses a Outermost (lazy) reduction.
remdups [3,7,3,7,5,7]
3:remdups (removeone 3 [7,3,7,5,7]) -- 9
3:remdups (7:(removeone 3 [3,7,5,7])) -- 5
3:7:remdups (removeone 7 (removeone 3 [3,7,5,7])) -- 9
3:7:remdups (removeone 7 (removeone 3 [7,5,7])) -- 4
3:7:remdups (removeone 7 (7:(removeone 3 [5,7]))) -- 5
3:7:remdups (removeone 7 (removeone 3 [5,7])) -- 4
3:7:remdups (removeone 7 (5:(removeone 3 [7]))) -- 5
3:7:remdups (5:(removeone 7 (removeone 3 [7]))) -- 5
3:7:5:remdups (removeone 5 (removeone 7 (removeone 3 [7]))) -- 9
3:7:5:remdups (removeone 5 (removeone 7 (7:(removeone 3 [])))) -- 5
3:7:5:remdups (removeone 5 (removeone 7 (removeone 3 []))) -- 4
3:7:5:remdups (removeone 5 (removeone 7 [])) -- 2
3:7:5:remdups (removeone 5 []) -- 2
3:7:5:remdups [] -- 2
3:7:5:[] -- 8
For completeness, there are other reduction procedures. For example leftmost-innermost (greedy) reduction. In this sample is the same result but for example head $ remdups [1..] greedy reduction would 'hang'. So as I know, that the leftmost-innermost is used only theoretically or for memory optimization:
remdups [3,7,3,7,5,7]
3:remdups (removeone 3 [7,3,7,5,7])
3:remdups (7:(removeone 3 [3,7,5,7]))
3:remdups (7:(removeone 3 [7,5,7]))
3:remdups (7:(7:(removeone 3 [5,7])))
3:remdups (7:(7:(5:(removeone 3 [7]))))
3:remdups (7:(7:(5:(7:(removeone 3 [])))))
3:remdups (7:(7:(5:(7:([])))))
3:remdups [7,7,5,7] -- shorthand
3:7:remdups (removeone 7 [7,5,7])
3:7:remdups (removeone 7 [5,7])
3:7:remdups (5:(removeone 7 [7]))
3:7:remdups (5:(removeone 7 []))
3:7:remdups (5:([]))
3:7:remdups [5] -- shorthand
3:7:5:remdups (removeone 5 [])
3:7:5:remdups ([])
3:7:5:remdups [] -- shorthand
3:7:5:[]
[3,7,5] -- shorthand
In pseudocode, we have
rem1 x (x:t) = rem1 x t
rem1 x (a:t) = a:rem1 x t ; rem1 x [] = []
remdups (a:t) = a:remdups (rem1 a t) ; remdups [] = []
Innermost-Leftmost (eager evaluation):
remdups [3,7,3,7,5,7]
= 3: remdups (rem1 3 [7,3,7,5,7])
= 3: remdups (7:rem1 3 [3,7,5,7])
= 3: remdups (7: rem1 3 [7,5,7])
= 3: remdups (7:7: rem1 3 [5,7])
= 3: remdups (7:7:5: rem1 3 [7])
= 3: remdups (7:7:5:7: rem1 3 [])
= 3: remdups (7:7:5:7: [] )
= 3: 7: remdups (rem1 7 (7:5:7:[]))
= 3: 7: remdups ( rem1 7 (5:7:[]))
= 3: 7: remdups ( 5:rem1 7 (7:[]))
= 3: 7: remdups ( 5: rem1 7 ([]))
= 3: 7: remdups ( 5: [] )
= 3: 7: 5: remdups (rem1 5 [] )
= 3: 7: 5: remdups []
= 3: 7: 5: [] -- 15 reductions
Outermost (what Haskell is doing):
remdups [3,7,3,7,5,7]
= 3: remdups (rem1 3 [7,3,7,5,7])
= 3: remdups (7:rem1 3 [3,7,5,7])
= 3: 7: remdups (rem1 7 (rem1 3 [3,7,5,7]))
= 3: 7: remdups (rem1 7 ( rem1 3 [7,5,7]))
= 3: 7: remdups (rem1 7 (7: rem1 3 [5,7]))
= 3: 7: remdups (rem1 7 ( rem1 3 [5,7]))
= 3: 7: remdups (rem1 7 ( 5: rem1 3 [7]))
= 3: 7: remdups (5:rem1 7 ( rem1 3 [7]))
= 3: 7: 5: remdups (rem1 5 (rem1 7 ( rem1 3 [7])))
= 3: 7: 5: remdups (rem1 5 (rem1 7 ( 7: rem1 3 [])))
= 3: 7: 5: remdups (rem1 5 (rem1 7 ( rem1 3 [])))
= 3: 7: 5: remdups (rem1 5 (rem1 7 [] ))
= 3: 7: 5: remdups (rem1 5 [] )
= 3: 7: 5: remdups []
= 3: 7: 5: [] -- 15 reductions
Related
I have built a long nested list having the following profile:
set my-list [A 1 2 3 4] [B 5 6 7 8] [C 9 10 11 12]
I'd like to apply the meancommand to the fourth item of each nested lists, so in the example to
4 8 12
but without building a list in loop that would look like [4 8 12] (to save computing time).
Is it possible ?
using let comp mean (item i item 4 (my-list)) or let comp mean (item 4 (my-list)) aren't obviously working.
The answer would be useful to other part of the model that I'm building.
Thanks for your time.
The map primitive is very well suited for these sorts of calculations with lists. It allows you to perform a reporter separately for each part of a list and then returns the results as a new list.
let test-list [1 2 3]
show map [x -> x + 1] test-list
;> [2 3 4]
In your case, you would use map to cycle through your list of lists, and use the item primitive to extract the necessary number from each sublist (map [x -> item 4 x ] my-list). This then returns them as a list of which you can take the mean.
to check-mean-2
let my-list [["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
let my-mean mean map [x -> item 4 x ] my-list
print my-mean
end
EDIT: Although mine looks more efficient on first glance, Matteo's version actually runs quicker (at least on my machine)
globals [my-list]
to setup
set my-list [["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
end
to check-mean
let timer-list []
repeat 10 [
reset-timer
repeat 1000000 [
let the-sum 0
let i 0
while [i < length my-list] [
set the-sum (the-sum + item 4 (item i my-list))
set i i + 1
]
let my-mean the-sum / i
]
let the-timer timer ; ~0.207
show the-timer
set timer-list lput the-timer timer-list
]
show word "mean: " (mean timer-list) ; 0.210
end
to check-mean-2
let timer-list []
repeat 10 [
reset-timer
repeat 1000000 [
let my-mean mean map [x -> item 4 x ] my-list
]
let the-timer timer
show the-timer
set timer-list lput the-timer timer-list
]
show word "mean: " (mean timer-list) ; 0.235
end
ANOTHER EDIT: Finally two more versions using reduce instead of map. Version 3 is the fastest of them all but you should take notice of the fact that my-list has a 0 added to it in this version. This might make is slightly less conveniet for other purposes. You can also add this 0 to it during the calculation as seen in version 4, but that drives up the time again.
to check-mean-3
set my-list [0 ["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
let timer-list []
repeat 10 [
reset-timer
repeat 1000000 [
let my-sum reduce [ [x y] -> x + item 4 y] my-list
let my-mean my-sum / (length my-list - 1)
]
let the-timer timer
show the-timer
set timer-list lput the-timer timer-list
]
show word "mean: " (mean timer-list) ; 0.170
end
to check-mean-4
set my-list [["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
let timer-list []
repeat 10 [
reset-timer
repeat 1000000 [
let my-new-list fput 0 my-list
let my-sum reduce [ [x y] -> x + item 4 y] my-new-list
let my-mean my-sum / (length my-list - 1)
]
let the-timer timer
show the-timer
set timer-list lput the-timer timer-list
]
show word "mean: " (mean timer-list) ; 0.226
end
First things first: did you mean to say that such nested list is built such as the one below?
set my-list [[A 1 2 3 4] [B 5 6 7 8] [C 9 10 11 12]]
Note the extra pair of square brackets, that make this actually a list of lists. Even if that was the case, NetLogo wouldn't let you use that syntax:
Either because A, B and C are lacking quotation marks if you intend them to be strings;
Or because, if A, B and C are variables, NetLogo expects literal values (we can get around this problem by using (list ...) instead of []).
In the first case, it would have to be:
set my-list [["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
In the second case, it would have to be:
set my-list (list (list a 1 2 3 4) (list b 5 6 7 8) (list c 9 10 11 12))
All of the above just to make sure we are all on the same page (in general, please make sure that the code you post in your question is valid for the language you are asking about. As you can see, it would save a lot of time and space!).
Anyway I imagine that what you come up with is something of this type:
[["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
I would use a while loop to iterate through the inner lists. You can create a local variable to keep track of the sum of the numbers you extract as you iterate through the inner lists, and then divide that sum by the number of times you extracted a number:
to check-mean
let my-list [["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
let the-sum 0
let i 0
while [i < length my-list] [
set the-sum (the-sum + item 4 (item i my-list))
set i i + 1
]
print the-sum / i
end
From the answers above and adding a step in the procedure (mean and sd for groups of items having the same "region" in the list), here-below is my final code using map as the mean and sd are already calculated in a while-loop. Moreover, I assumed that calculating manually the standard deviation would create even more lists of list and complicate the code.
to create-successor-list
set successor-list map [inner-list -> (list inner-list 0 0 ) ] region-data
let i 0
while [i < length region-data] [
let current-item item i region-data
set temp-profitability-list (filter [current-inner-list -> (item 1 current-inner-list = current-item)] profitability-list )
set prof-mean mean map [x -> item 4 x ] temp-profitability-list
set prof-sd standard-deviation map [x -> item 4 x ] temp-profitability-list
set successor-list replace-item i successor-list (replace-item 1 item i successor-list (prof-mean))
set successor-list replace-item i successor-list (replace-item 2 item i successor-list (prof-sd))
set i i + 1
set temp-profitability-list [ ]
]
end
I would like to ask how to choose increasing subsequence of elements from a list in Haskell. The rule is that in a not empty list the first element is chosen and then every element that is bigger than the previously chosen element. For example in a list [3,1,8,4,6,7,9,2,11,4,3]
would be chosen sublist [3,8,9,11].
My code so far doesn't cover the problem completely:
incrSub :: Ord a => [a] -> [a]
incrSub [] = []
incrSub (x:xs) = if x < head xs then x: incrSub (xs) else incrSub (xs)
Consider the evaluation of your function on the provided sample input:
incrSub [3, 1, 8, 4, 6, 7, 9, 2, 11, 4, 3]
incrSub (3 : 1 : 8 : 4 : 6 : 7 : 9 : 2 : 11 : 4 : 3 : [])
3 < 1 == False → incrSub (1 : 8 : 4 : 6 : 7 : 9 : 2 : 11 : 4 : 3 : [])
1 < 8 == True → 1 : incrSub (8 : 4 : 6 : 7 : 9 : 2 : 11 : 4 : 3 : [])
8 < 4 == False → 1 : incrSub (4 : 6 : 7 : 9 : 2 : 11 : 4 : 3 : [])
4 < 6 == True → 1 : 4 : incrSub (6 : 7 : 9 : 2 : 11 : 4 : 3 : [])
6 < 7 == True → 1 : 4 : 6 : incrSub (7 : 9 : 2 : 11 : 4 : 3 : [])
7 < 9 == True → 1 : 4 : 6 : 7 : incrSub (9 : 2 : 11 : 4 : 3 : [])
9 < 2 == False → 1 : 4 : 6 : 7 : incrSub (2 : 11 : 4 : 3 : [])
2 < 11 == True → 1 : 4 : 6 : 7 : 2 : incrSub (11 : 4 : 3 : [])
11 < 4 == False → 1 : 4 : 6 : 7 : 2 : incrSub (4 : 3 : [])
4 < 3 == False → 1 : 4 : 6 : 7 : 2 : incrSub (3 : [])
3 < undefined == undefined → 1 : 4 : 6 : 7 : 2 : undefined
Notice the relationship between the actual result and the expected result:
input 3 : 1 : 8 : 4 : 6 : 7 : 9 : 2 : 11 : 4 : 3 : []
expected 3 : 8 : 9 : 11 : []
actual 1 : 4 : 6 : 7 : 2 : undefined
So this suggests a few things to look at:
Your condition is filtering the opposite of what you intended.
You are not handling the end of the list correctly. In particular, consider the case of a 1-element list incrSub [42].
Your code is prone to errors because you’re using head, which is a partial function. Preferring pattern-matching may help, especially if you enable warnings (e.g. passing -Wall to GHC or adding {-# GHC_OPTIONS -Wall #-} to your file). Recall that you can use nested patterns like x1 : x2 : xs to match a list of at least 2 elements x1 and x2.
Working through examples like this using equational reasoning is a very powerful debugging technique for Haskell code. You can also use property-based testing libraries like QuickCheck to identify test cases that fail. For example, it quickly identifies the minimal failing test case of singleton lists:
> import Test.QuickCheck (quickCheck)
> resultIsSorted :: [Int] -> Bool; resultIsSorted input = let { result = incrSub input } in result == sort result
> quickCheck resultIsSorted
*** Failed! Exception: 'Prelude.head: empty list' (after 2 tests and 2 shrinks):
[0]
You can write more complex properties to find more interesting edge cases.
I have stored a directed graph in a 2D vector and I want to iterate through all the possible path from any directed graph going from left to right via groups in a recursive manner. I have given an example below and want to iterate through all the paths from the first group (in this example G1) to any last group (in this example G3). I have been trying a lot but I'm not able to build a recursive to iterate through all the paths with any amount of groups. So I need help with building a manual iteration system/algorithm of loops without recursion function calls. For the iteration part, if I can get an algorithm which can print all the possible paths, it will be more than helpful. So, any source, tips and tricks will be useful. Thanks.
graph:
script.cpp
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> map = {
{ 1, 2 },
{ 3, 4, 5 },
{ 6, 7 }
};
// Print all paths
// Note :- every array in the map is a group
return 0;
}
output:
1 -> 3 -> 6
1 -> 3 -> 7
1 -> 4 -> 6
1 -> 4 -> 7
1 -> 5 -> 6
1 -> 5 -> 7
2 -> 3 -> 6
2 -> 3 -> 7
2 -> 4 -> 6
2 -> 4 -> 7
2 -> 5 -> 6
2 -> 5 -> 7
#Compile using g++ -std=c++11 code.cpp
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<vector<int> > map = {
{ 1, 2 },
{ 3, 4, 5 },
{ 6, 7 }
};
vector<int> sizes(map.size());
vector<int> indexes(map.size());
int combinations = 1;
for(int i=0; i<map.size();i++){
sizes[i]=map[i].size();
}
for(int i=0; i<map.size();i++){
combinations*=map[i].size();
}
for(int combination=1; combination <= combinations; combination++){
int multiple = 1;
for(int ind=0; ind<indexes.size(); ind++){
cout << map[ind][indexes[ind]];
if(ind < indexes.size()-1)
cout << " -> ";
}
cout << endl;
for(int j=map.size()-1;j>=0;j--){
multiple*=map[j].size();
indexes[map.size()-1]=combination % map[map.size()-1].size();
if(combination % multiple == 0 && j>0){
//cout << "*";
indexes[j-1] = (indexes[j-1]+1)%map[j-1].size();
}
}
}
return 0;
}
vector<vector<int> > map = {
{ 1, 2 },
{ 3, 4, 5, 10, 100 },
{ 6, 7, 8 },
{ 6, 7 },
{ 600, 17 }
};
1 -> 3 -> 6 -> 6 -> 600
1 -> 3 -> 6 -> 6 -> 17
1 -> 3 -> 6 -> 7 -> 600
1 -> 3 -> 6 -> 7 -> 17
1 -> 3 -> 7 -> 6 -> 600
1 -> 3 -> 7 -> 6 -> 17
1 -> 3 -> 7 -> 7 -> 600
1 -> 3 -> 7 -> 7 -> 17
1 -> 3 -> 8 -> 6 -> 600
1 -> 3 -> 8 -> 6 -> 17
1 -> 3 -> 8 -> 7 -> 600
1 -> 3 -> 8 -> 7 -> 17
1 -> 4 -> 6 -> 6 -> 600
1 -> 4 -> 6 -> 6 -> 17
1 -> 4 -> 6 -> 7 -> 600
1 -> 4 -> 6 -> 7 -> 17
1 -> 4 -> 7 -> 6 -> 600
1 -> 4 -> 7 -> 6 -> 17
1 -> 4 -> 7 -> 7 -> 600
1 -> 4 -> 7 -> 7 -> 17
1 -> 4 -> 8 -> 6 -> 600
1 -> 4 -> 8 -> 6 -> 17
1 -> 4 -> 8 -> 7 -> 600
1 -> 4 -> 8 -> 7 -> 17
1 -> 5 -> 6 -> 6 -> 600
1 -> 5 -> 6 -> 6 -> 17
1 -> 5 -> 6 -> 7 -> 600
1 -> 5 -> 6 -> 7 -> 17
1 -> 5 -> 7 -> 6 -> 600
1 -> 5 -> 7 -> 6 -> 17
1 -> 5 -> 7 -> 7 -> 600
1 -> 5 -> 7 -> 7 -> 17
1 -> 5 -> 8 -> 6 -> 600
1 -> 5 -> 8 -> 6 -> 17
1 -> 5 -> 8 -> 7 -> 600
1 -> 5 -> 8 -> 7 -> 17
1 -> 10 -> 6 -> 6 -> 600
1 -> 10 -> 6 -> 6 -> 17
1 -> 10 -> 6 -> 7 -> 600
1 -> 10 -> 6 -> 7 -> 17
1 -> 10 -> 7 -> 6 -> 600
1 -> 10 -> 7 -> 6 -> 17
1 -> 10 -> 7 -> 7 -> 600
1 -> 10 -> 7 -> 7 -> 17
1 -> 10 -> 8 -> 6 -> 600
1 -> 10 -> 8 -> 6 -> 17
1 -> 10 -> 8 -> 7 -> 600
1 -> 10 -> 8 -> 7 -> 17
1 -> 100 -> 6 -> 6 -> 600
1 -> 100 -> 6 -> 6 -> 17
1 -> 100 -> 6 -> 7 -> 600
1 -> 100 -> 6 -> 7 -> 17
1 -> 100 -> 7 -> 6 -> 600
1 -> 100 -> 7 -> 6 -> 17
1 -> 100 -> 7 -> 7 -> 600
1 -> 100 -> 7 -> 7 -> 17
1 -> 100 -> 8 -> 6 -> 600
1 -> 100 -> 8 -> 6 -> 17
1 -> 100 -> 8 -> 7 -> 600
1 -> 100 -> 8 -> 7 -> 17
2 -> 3 -> 6 -> 6 -> 600
2 -> 3 -> 6 -> 6 -> 17
2 -> 3 -> 6 -> 7 -> 600
2 -> 3 -> 6 -> 7 -> 17
2 -> 3 -> 7 -> 6 -> 600
2 -> 3 -> 7 -> 6 -> 17
2 -> 3 -> 7 -> 7 -> 600
2 -> 3 -> 7 -> 7 -> 17
2 -> 3 -> 8 -> 6 -> 600
2 -> 3 -> 8 -> 6 -> 17
2 -> 3 -> 8 -> 7 -> 600
2 -> 3 -> 8 -> 7 -> 17
2 -> 4 -> 6 -> 6 -> 600
2 -> 4 -> 6 -> 6 -> 17
2 -> 4 -> 6 -> 7 -> 600
2 -> 4 -> 6 -> 7 -> 17
2 -> 4 -> 7 -> 6 -> 600
2 -> 4 -> 7 -> 6 -> 17
2 -> 4 -> 7 -> 7 -> 600
2 -> 4 -> 7 -> 7 -> 17
2 -> 4 -> 8 -> 6 -> 600
2 -> 4 -> 8 -> 6 -> 17
2 -> 4 -> 8 -> 7 -> 600
2 -> 4 -> 8 -> 7 -> 17
2 -> 5 -> 6 -> 6 -> 600
2 -> 5 -> 6 -> 6 -> 17
2 -> 5 -> 6 -> 7 -> 600
2 -> 5 -> 6 -> 7 -> 17
2 -> 5 -> 7 -> 6 -> 600
2 -> 5 -> 7 -> 6 -> 17
2 -> 5 -> 7 -> 7 -> 600
2 -> 5 -> 7 -> 7 -> 17
2 -> 5 -> 8 -> 6 -> 600
2 -> 5 -> 8 -> 6 -> 17
2 -> 5 -> 8 -> 7 -> 600
2 -> 5 -> 8 -> 7 -> 17
2 -> 10 -> 6 -> 6 -> 600
2 -> 10 -> 6 -> 6 -> 17
2 -> 10 -> 6 -> 7 -> 600
2 -> 10 -> 6 -> 7 -> 17
2 -> 10 -> 7 -> 6 -> 600
2 -> 10 -> 7 -> 6 -> 17
2 -> 10 -> 7 -> 7 -> 600
2 -> 10 -> 7 -> 7 -> 17
2 -> 10 -> 8 -> 6 -> 600
2 -> 10 -> 8 -> 6 -> 17
2 -> 10 -> 8 -> 7 -> 600
2 -> 10 -> 8 -> 7 -> 17
2 -> 100 -> 6 -> 6 -> 600
2 -> 100 -> 6 -> 6 -> 17
2 -> 100 -> 6 -> 7 -> 600
2 -> 100 -> 6 -> 7 -> 17
2 -> 100 -> 7 -> 6 -> 600
2 -> 100 -> 7 -> 6 -> 17
2 -> 100 -> 7 -> 7 -> 600
2 -> 100 -> 7 -> 7 -> 17
2 -> 100 -> 8 -> 6 -> 600
2 -> 100 -> 8 -> 6 -> 17
2 -> 100 -> 8 -> 7 -> 600
2 -> 100 -> 8 -> 7 -> 17
Here is the solution in recursive way:
#include <iostream>
#include <vector>
using namespace std;
void solve(vector < vector<int> >map, vector<int>ans, int pos) {
if(pos == map.size()) {
for(int i = 0; i < ans.size(); i++) {
cout<<ans[i];
if(i != ans.size() - 1) {
cout<<"->";
}
else {
cout<<endl;
}
}
return;
}
for(int i = 0; i < map[pos].size(); i++) {
ans.push_back(map[pos][i]);
solve(map, ans, pos+1);
ans.pop_back();
}
}
int main() {
vector<vector<int> > map = {
{ 1, 2 },
{ 3, 4, 5 },
{ 6, 7 }
};
vector<int>empty;
solve(map, empty, 0);
}
Output:
1->3->6
1->3->7
1->4->6
1->4->7
1->5->6
1->5->7
2->3->6
2->3->7
2->4->6
2->4->7
2->5->6
2->5->7
I am trying to create a function rationalSumLowest that takes an Int n and returns a list of ratio numbers that sum to n, but only showing the ratio numbers that are already in reduced form. I have attempted to do this by creating the following functions:
mergeArrays :: [Int] -> [Int] -> [Ratio Int]
mergeArrays [] [] = []
mergeArrays (x:xs) (y:ys) = [x%y] ++ mergeArrays xs ys
rationalSum :: Int -> [Ratio Int]
rationalSum 0 = []
rationalSum 1 = []
rationalSum n = mergeArrays [1..(n-1)] [(n-1), (n-2)..1]
sumLowestBool :: Ratio Int -> Bool
sumLowestBool x
|(gcd (extractNumerator (x)) (extractDenominator (x)) == 1) = True
|otherwise = False
rationalSumLowest :: Int -> [Ratio Int]
rationalSumLowest 0 = []
rationalSumLowest 1 = []
rationalSumLowest n = [i | i <- rationalSum (n), sumLowestBool i == True]
It should run like this:
*Main> rationalSumLowest 5
[1 % 4,2 % 3,3 % 2,4 % 1]
*Main> rationalSumLowest 8
[1 % 7,3 % 5,5 % 3,7 % 1]
*Main> rationalSumLowest 12
[1 % 11,5 % 7,7 % 5,11 % 1]
With rationalSum running like this:
*Main> rationalSum 5
[1 % 4,2 % 3,3 % 2,4 % 1]
*Main> rationalSum 8
[1 % 7,1 % 3,3 % 5,1 % 1,5 % 3,3 % 1,7 % 1]
*Main> rationalSum 1
[]
My rationalSum function works properly, but my rationalSumLowest function does not. It returns the same list as the rationalSum function. I know this is because in Haskell, all ratios are automatically reduced and thus my sumLowestBool would return True for all entries in the list.
My question is: is there a way to keep the non-reduced form of the ratio in the original list so that my sumLowestBool function can work properly?
Since the ratios are reduced, checking that the gcd is 1 is the same as checking that the numerator hasn't changed.
import Data.Ratio
rationalSumLowest :: Integer -> [Rational]
rationalSumLowest n =
[ v
| i <- [1 .. n-1]
, let v = i % (n-i)
, numerator v == i
]
I'm new to haskell and I want to sort list of strings. For example I have a list that is in my variable ff that contain three strings ["1 8 8 5 6", "1 4 2 3", "5 4 9 7 9 9"] and I want to sort them so my result should look like ["1 5 6 8 8", "1 2 3 4", "4 5 7 9 9 9"] Here's my code that perfectly works
import System.IO
import Control.Monad
import Data.List
import Data.Function
import Data.Array
import Data.Char
sortNumeric = sortBy (compare `on` (read :: String -> Int))
wordsWhen :: (Char -> Bool) -> String -> [String]
wordsWhen p s = case dropWhile p s of
"" -> []
s' -> w : wordsWhen p s''
where (w, s'') = break p s'
main = do
file <- readFile "test.txt"
let ff = map ((!!) (lines file)) [1,3..(length (lines file) - 1)]
let splitString = wordsWhen (==' ') (ff!!0)
let sortedResult = sortNumeric (splitString)
print sortedResult
Problem is with this line let splitString = wordsWhen (==' ') (ff!!0) I always get first element of the list, so only first element is sorted. How can I pass all values of a list? Here's what I tryied to do let splitString = wordsWhen (==' ') (ff!![0..(length(ff)-1)]) unfortunately this doesn't work. Any ideas how to solve this problem?
You can do it easily with map and a niftry trick to use words, sort and then unwords (to restore the whitespace).
Prelude> let ff=["1 8 8 5 6", "1 4 2 3", "5 4 9 7 9 9"]
Prelude> import Data.List
Prelude Data.List> map (unwords . sort . words) ff
["1 5 6 8 8","1 2 3 4","4 5 7 9 9 9"]
Edit: Improvement to correctly sort numeric values:
import Data.List
let ff=["11 8 8 5 6", "11 4 2 3", "5 4 9 7 99 9"]
let sortNumeric = (map show) . sort . (map (read :: String -> Int))
map (unwords . sortNumeric . words) ff
result:
["5 6 8 8 11","2 3 4 11","4 5 7 9 9 99"]