Merge sort, the recursion part - recursion

After studying the merge sort for a couple of days, I understand it conceptually, but there is one thing that I don't get.
What I get:
1.) It takes a list, for example an array of numbers and splits it in half and sorts the two halfs, and in the end merges them together.
2.) Because it's an recursive algorithm it uses recursion to do that.
So the split of the mentioned array looks like this:
It, splits the array until there is only one item in each list and by that its considered sorted. And at that point the merge steps in.
Which should look like this:
What I don't get is, how does the recursion "know" after it splits all the lists to only one item in a list, to get back up the recursion tree? How does something that has a left and right side become the left side after it merges?
The thing that bothers me is this. I've taken a snapshot of the code from interactivepython page
How does the code get to the point, after we have lefthalf = 2, and righthalf = 1, to to code that's shown in the picture where the lefthalf = [1,2] and righthalf = [4,3] without going back to the recursion that would divide what we have have merged?
Tnx,
Tom

Once the list only contains one element, each pair of leaves are sorted and joined. Then you can traverse through the list and find out where the next pair should be inserted. The recursion "knows" nothing about going back up the recursion tree, rather it is the act of sorting and joining that has this effect.

The "recursion" does of course know nothing of that sort. It is the code that uses the recursion, which looks like this (a bit simplified):
sort list = merge (sort left_half) (sort right_half)
where
(left_half, right_half) = split list
Here you see that the "recursion" (i.e. the recursive invocations of sort) don't need to "know" anything. Their only job is to deliver a sorted list, array or whatever.
To put it differently: If we have merge satisfying the following invariant:
1. `merge`, given two sorted lists, will return a sorted list.
then we can write mergesort easily like outlined above. What is left to do in sort is to handle the easy cases: empty list, singleton and list with two elements.

If you are talking about odd numbered sub lists, then it is dependant on the implementation.
It either puts the bigger sub list on the left every single time, or it puts it on the right every single time.

Related

Replacing a symbol in a .txt file

Alright, I've been given a program that requires me to take a .txt file of varying symbols in rows and columns that would look like this.
..........00
...0....0000
...000000000
0000.....000
............
..#########.
..#...#####.
......#####.
...00000....
and using command arguments to specify row and column, requires me to select a symbol and replace that symbol with an asterisk. The problem i have with this is that it then requires me to recur up, down, left, and right any of the same symbol and change those into an asterisk.
As i understand it, if i were to enter "1 2" into my argument list it would change the above text into.
**********00
***0....0000
***000000000
0000.....000
............
..#########.
..#...#####.
......#####.
...00000....
While selecting the specified character itself isn't a problem, how do i have any similar, adjacent symbols change and then the ones next to those. I have looked around but can't find any information and as my teacher has had a different subs for the last 3 weeks, i havent had a chance to clarify my questions with them. I've been told that recursion can be used, but my actual experience using recursion is limited. Any suggestions or links i can follow to get a better idea on what to do? Would it make sense to add a recursive method that takes the coordinates given adds and subtracts from the row and column respectively to check if the symbol is the same and repeats?
Load in char by char, row by row, into a 2D array of characters. That'll make it a lot easier to move up and down and left and right, all you need to do is move one of the array indexes.
You can also take advantage of recursion. Make a function that changes all adjacent matching characters, and then call that same function on all adjacent matching characters.

Idiomatic way to spilt sequence into three lists using Kotlin

So this is possibly more about functional programming than Kotlin, I am at that stage were a little knowledge is dangerous, and I wrote the app in Kotlin so seems fair to ask a Kotlin question as its Kotlins structures that i am interested in.
I have a sequence of items, they are in batches of three, so the stream may look like
1,a,+,2,b,*,3,c,&.......
What I want to do is to spilt this into three lists, currently I am doing this by partitioning into two lists, one that contains the numbers and one that contains everything else, then taking the second half of the result, the letters and symbols and partitioning again, into letters and symbols, thus i end up with three lists.
This strikes me as somewhat inefficient, maybe a functional approach isn't the best approach here.
Is there an efficient way of doing this, are my choices, this or a for loop?
Thanks
You can use groupBy method to group elements of your sequence by an element type:
val elementsByType = sequence.groupBy { getElementType(it) }
where getElementType is function returning a type of the element: whether it is a letter, or a number, or a symbol. This function may return either a number, such as 1, 2, 3, or a value of some enum with 3 different entries.
groupBy returns a map from element type to list of elements of that type.

Prolog, add list of list together to make one list

Hi I need to write a Prolog predicate that will sum the lines of a list of list so given
|a,b,c| |j,k,l| |s,t,u|
|d,e,f| |m,n,o| |v,w,x|
|g,h,i|.|p,q,r|,|y,z,?|
/*I want to be able to get back */
|(a+j+s),(b+k+t),(c+l+u)|
|(d+m+v),(e+n+w),(f+o+x)|
|(g+p+y),(h+q+z),(i+r+?)|
Im having a hard time because I want to add the head to the head of the tail, and so on but can't figure out away to tell prolog to do that. I can add any one line at a time or even just two matrices but given a list like this I cannot see to get it. Any help would be appreciated. Thanks.

How to select all elements of a list at a particular nested Level?

Or put it differently: How can I use the [[ operator in a nested list?
You can consider this as a follow-up question on this one, when I asked how to determine the depth level of a list. I got some decent answers from #Spacedman and #flodel who both suggested recursive functions. Both solutions where quite similar and worked for me.
However I haven't figured out yet what to do with the information I get from these functions. Let's say I have a list nested at level i and I want to get back a list that contains all i-th level elements, like this:
myList$firstLevel$secondLevel$thirdLevel$fourthLevel
# fourthLevel contains 5 data.frames and thirdLevel has
# three elements
How can I get back all 15 data.frames from mylist?
I am trying to use e.g.
lapply(mylist,"[[",2)
but obviously I just get the second element of all list elements at the first level.
EDIT: I found the following in the help of extract respectivel ?"[[" but can't really wrap my head around it so far:
"[[ can be applied recursively to lists, so that if the single index i is a vector of length p, alist[[i]] is equivalent to alist[[i1]]...[[ip]] providing all but the final indexing results in a list."
EDIT:
Don't want to end up nesting loops like this.
o <- list()
i=1
for (i in 1:2){
o[[i]] <- mylist[[c(i,1,1,1)]]
}
I found the answer in the meantime. Can't say say I did it on my own. This
link gives an elaborate explanation how to use another (complex) recursive function to linearize the whole nested list wad.
What's really nice about the solution provided by Akhil S. Behl: it deals with the fact that data.frames are lists too and recursing can stop before data.frames. It turned out that this was one of my major problems before.

Matching specific items in several discrete collections

I have a problem whereby I have several discrete lists of ID's eg.
List (A) 1,2,3,4,5,7,8
List (B) 2,3,4,5
List (C) 4,2,8,9,1
etc...
I then have another collection of ID's...
For example: 1,2,4
I need to try and match one into each list. If I can perfectly match all ID's in my secondary collection (one collection ID matched with an ID from each list) then I get a true result....
I have found that it becomes complicated because if you simply iterate over the lists matching the first collection/list pair that you encounter it may result in you precluding a possible combination further on down the line hence returning a false negative result.
For example:
List (A) 1,2,3,4
List (B) 1,2,3,4
List (C) 3,4
Collection is: 3,1,2
The first ID from the collection (3) matches with an entry in list A, the second ID in the collection (1) matches an item in list B, however the final ID in the collection (2) DOESNT match any entry in list C however if you rearrange the order of the collection to be: 2,1,3 then a match is found.... Therefore I am looking for some form of logic for attempting a match on all possible combinations in an efficient manner(?)
To make it more complicated the ID's are actually GUID's so cant just be sorted in ascending order
I hope I have described this well enough to make it clear what I am attempting and with a bit of luck somebody will be able to tell me that what I need to do is very easy and I am missing something real simple!
I am forced to code this in VB6 but any methods or pseudo code would be great. The backend of this is SQL server so if a solution using TSQL was possible this would be even better as all of the ID's are held in tables already.
Many thanks in advance.
Jake, yep the lists and the collection both contain GUIDS. I used plain integers to simplify the problem a bit.
Once a list has been matched it cant be searched again, hence the ordering problem that I tried to explain. If you say that a list as 'matched' then no further attempts to match this will be performed. It is this very behaviour that can cause a false negative.
'Sending' the collection in in every possible combination of orders would work but would be a massive job .....
I feel I must be missing a really straightforward concept or solution here??!!
Thanks for your assistance so far.
I don't see a way around checking each GUID contained in the lists against each GUID in the collection. You would have to keep record of in which lists each GUID in the collection occurs.
To use your example of the Collection (3, 1, 2), 3 occurs in List A, B and C.
You will basically be left with this dataset.
3 (A, B, C)
1 (A, B)
2 (A, B)
Once you have distilled it down to this dataset you can determine whether there are any GUIDs with zero occurrences in the lists which would result in a negative.
I am not at all well versed in algorithms, but this is how I would proceed after that :
Start with the first set (A, B, C), and check how many times it occurs further on in the dataset. In this case no occurrences are found.
Moving on to the next set (A, B), if the number of occurrences of this set is found to be greater than the length of this set, i.e. more than two occurrences, would result in a negative. If the number of occurrences match the length exactly, as is the case here, the set (A, B) can be removed from any further consideration.
3 (C)
1 ()
2 ()
I guess you would continue to repeat the process until a negative is identified or all the occurrences have been excluded. There is probably a recognized algorithm for this sort of problem, but my knowledge is a bit lacking in that respect. :(

Resources