It's your first day at work as an intern, and your boss explains a major problem: "Our only developer quit yesterday, and he left this note on his desk. We need to know what it does. If you can figure it out, we'll promote you to his job."
#PSEUDOCODE
mystery(list):
if list is empty then return the empty list
otherwise:
let list1 consist of all elements of list that are <= first element, excluding the first element itself
let list2 consist of only the first element of list
let list3 consist of all elements of list that are > first element
return mystery(list1) + list2 + mystery(list3) # + indicates list concatenation
thelist = [1, 4, 2, 3, 3, 45, 6, 7, 8, 5, 4, 3, 2, 21, 2, 3, 4, 5, 6, 7]
newlist = mystery(thelist)
total = 0
for i in range(5):
total += newlist[i]
print total
So, what is this code supposed to print?
Details and assumptions
1. To make it clear what is meant by list concatenation, here is an example:
[
2
,
7
]
+
[
8
,
9
,
3
]
=
[
2
,
7
,
8
,
9
,
3
]
.
2. Note that mystery is a recursive function (it calls itself at the last step).
This section requires Javascript.
You are seeing this because something didn't load right. We suggest you, (a) try
refreshing the page, (b) enabling javascript if it is disabled on your browser and,
finally, (c)
loading the
non-javascript version of this page
. We're sorry about the hassle.
This is not quicksort. It is closer to mergesort.
It's not mergesort, because there's no merge step; mystery() just divides the list into elements that are greater and lesser than a particular value (a pivot), which is what quicksort does. Quicksort implementations don't usually create a new array (sorting is usually done in-place) but this is essentially exactly quicksort.
Meant to write "exactly," not "essentially exactly." oops.
Yes, you are right. I was confused. The "no merge step" should have been a clear sign that this is not merge sort yet I managed to ignore it :)
Here is the Python code that solves this problem. It's really interesting how little I have to do to get the pseudocode into Python giving the answer of 1 0 . :D
def mystery(list):
if len(list) == 0:
return list
else:
list1 = [i for i in list if i <= list[0]]
list1.pop(0)
list2 = [list[0]]
list3 = [i for i in list if i > list[0]]
return mystery(list1) + list2 + mystery(list3)
thelist = [1, 4, 2, 3, 3, 45, 6, 7, 8, 5, 4, 3, 2, 21, 2, 3, 4, 5, 6, 7]
newlist = mystery(thelist)
total = 0
for i in range(5):
total += newlist[i]
print total
Below is C# code for this namespace Mystery { class Myst { public List<int> Mystrey(List<int> firstList) { if (firstList.Count == 0) { return new List<int>(); } else { List<int> list1 = getList1(firstList); List<int> list2 = new List<int>(); list2.Add(firstList.ElementAt(0)); List<int> list3 = getList3(firstList);
return Mystrey(list1).Concat(list2).Concat(list3).ToList();
}
}
private List<int> getList1(List<int> L1)
{
List<int> temp = new List<int>();
int first=L1.ElementAt(0);
foreach (int i in L1)
{
if (i <= first)
{
temp.Add(i);
}
}
temp.RemoveAt(0);
return temp;
}
private List<int> getList3(List<int> L1)
{
List<int> temp = new List<int>();
int first = L1.ElementAt(0);
foreach (int i in L1)
{
if (i > first)
{
temp.Add(i);
}
}
return temp;
}
}
class Program
{
static void Main(string[] args)
{
Myst M = new Myst();
List<int> theList = new List<int>()
{
1, 4, 2, 3, 3, 45, 6, 7, 8, 5, 4, 3, 2, 21, 2, 3, 4, 5, 6, 7
};
List<int> newList=M.Mystrey(theList);
int total = 0;
for (int i = 0; i < 4; i++)
{
total += newList[i];
}
Console.WriteLine("total is:"+total);
}
}
}
Here's a Haskell version for anybody... even shorter than the pseudocode because the otherwise statement is on one line.
mystery list
| list == [] = []
| otherwise = mystery list1 ++ list2 ++ mystery list3
where list1 = filter (<= head list) $ tail list
list2 = [head list]
list3 = filter (> head list) $ tail list
thelist = [1, 4, 2, 3, 3, 45, 6, 7, 8, 5, 4, 3, 2, 21, 2, 3, 4, 5, 6, 7]
newlist = mystery thelist
total = sum $ take 5 newlist
main = print total
It is very clear that mystery returns same list if it is empty or of length 1.
If list length is more than 1, then it clearly starts sorting recursively!
So, sort the list in ascending. But we need to find only first five - which are 1, 2, 2, 2, 3 total of which is 10!
The code is used to arrange values in ascending order. First five values are [1,2,2,2,3]. So the total is 10.
Solution in Python:
#PSEUDOCODE
def mystery(lst):
if lst == []:
return lst
else:
list1 = [] #let list1 consist of all elements of list that are <= first element, excluding the first element itself
for i in lst[1:]:
if i <= lst[0]:
list1.append(i)
list2 = [] #let list2 consist of only the first element of list
list2.append(lst[0])
list3 = [] #let list3 consist of all elements of list that are > first element
for i in lst[1:]:
if i > lst[0]:
list3.append(i)
return mystery(list1) + list2 + mystery(list3) # + indicates list concatenation
thelist = [1, 4, 2, 3, 3, 45, 6, 7, 8, 5, 4, 3, 2, 21, 2, 3, 4, 5, 6, 7]
newlist = mystery(thelist)
total = 0
for i in range(5):
total += newlist[i]
print total
>>> 10
Here is shorter version!
def mystery(l):
if len(l) == 0 or len(l) == 1:
return l
else:
lx = l[1:]
l1 = [x for x in lx if x <= l[0]]
l2 = [x for x in lx if x > l[0]]
return mystery(l1) + [l[0]] + mystery(l2)
Below is what you might categorize as a completely stupid and highly inefficient code. But my main motive at 3 am in the morning is only to solve the problem. Algorithmic efficiency is not very good. But it does the job.
//include iostream and include vector statement go here. //compile with any C++ compiler
using namespace std;
vector< int > addVector (vector< int > list1, vector< int > list2, vector< int > list3) {
int sizeToAdd = list1.size () + list2.size () + list3.size ();
vector< int > result (sizeToAdd);
int position (0);
for (int i = 0; i < list1.size (); i++) {
result [position] = list1 [i];
position++;
}
result [position] = list2 [0];
position++;
for (int i = 0; i < list3.size (); i++) {
result [position] = list3 [i];
position++;
}
return (result);
}
vector< int > mystery (vector< int > myList) {
if (myList.size () == 0) {
return (myList);
}
else {
int buffer (0);
vector< int > smallerList;
vector< int > greaterList;
vector< int > firstElem (1);
firstElem [0] = myList [0];
for (int i = 1; i < myList.size (); i++) {
if (myList [i] <= myList [0]) { buffer = myList [i]; smallerList.push_back (buffer); }
else if (myList [i] > myList [0]) { buffer = myList [i]; greaterList.push_back (buffer); }
}
return (addVector (mystery (smallerList), firstElem, mystery (greaterList)));
}
}
int main () {
int total (0);
int array [] = {1, 4, 2, 3, 3, 45, 6, 7, 8, 5, 4, 3, 2, 21, 2, 3, 4, 5, 6, 7};
vector< int > myList (20);
for (int i = 0; i < 20; i++) {
myList [i] = array [i];
}
vector< int > finalVector = mystery (myList);
for (int i = 0; i < 5; i++) {
total += finalVector [i];
}
cout << total << endl;
return (0);
}
The function mystery sorts the list in ascending order and the code prints sum of elements in places 2,3,4,5,6
The printed sum is of elements 1-5. Although strictly speaking, range() is left undefined, the intuitive behaviour for the for loop is to cycle through the first 5 elements. Actual code in Python (which I assume "range" was inspired from) also works this way.
Problem Loading...
Note Loading...
Set Loading...
Basically, mystery() is an implementation of quicksort (which sorts a list). Therefore, the sum of the first 5 elements of newlist is just the sum of the 5 least elements of thelist , which is 1 + 2 + 2 + 2 + 3 = 1 0 .