Can someone please tell me what is wrong with this logic? - c++

I was solving a question on Hackerrank. The following is the question (in brief):
There exist n robbers trying to rob a bank. They can stay there for atmost G minutes. Only two robbers can enter a vault at a time.
a[]={a_1,a_2,...,a_n} is a user specified array such that a_i is the time the i_th robber wishes to stay in the vault.
A heist is successful if all the robbers get their wish.
Given n,G, a[]; the output must be "success" or "failure".
My logic was as follows:
sort(a) in descending order
define slot1 and slot2 for 1st and 2nd person in vault respectively
slot1=slot2=G
fill in slot1 and slot2 from the sorted a, such that whenever a robber is finished in the slot, the next one takes his place
If all robbers can be accommodated, then success, else failure.

I would try having a double pass. First, add up all the time the robbers would want, then halve and round up. That's your ideal time. (at this point, check if one of your robbers is at/over this amount; if so, then that's your limit.) Then, try to fit robbers into that time frame. If you can fit them evenly, you're good. Otherwise, increase the time and try again.

Edit: As JonTheMon noted above, your approach would fail when G = 6 and a = {2, 2, 2, 3, 3}.
Anyway, your idea is wrong and you would not be able to solve the problem in such a way. Here is a hint:
This is a classical DP problem.
old post with wrong test case:
Let G = 4 and a[] = {1, 2, 2, 3}.
As far as I understood your approach, you will first accommodate robbers a_1 and a_2. After a_1 finished, you will introduce a_3 on his place. However, this leaves a_4 without enough time in a vault - only 2 minutes where he wanted to be inside at least 3.

Related

Riddle puzzle in clingo

So in the tag prolog someone wanted to solve the "the giant cat army riddle" by Dan Finkel (see video / Link for description of the puzzle).
Since I want to improve in answer set programming I hereby challenge you to solve the puzzle more efficient than me. You will find my solution as answer. I'll accept the fastest running answer (except if it's using dirty hacks).
Rules:
hardcoding the length of the list (or something similar) counts as dirty hack.
The output has to be in the predicate r/2, where it's first argument is the index of the list and the second its entry.
Time measured is for the first valid answer.
num(0..59).
%valid operation pairs
op(N*N,N):- N=2..7.
% no need to add operations that start with 14
op(Ori,New):- num(Ori), New = Ori+7, num(New), Ori!=14.
op(Ori,New):- num(Ori), New = Ori+5, num(New), Ori!=14.
%iteratively create new numbers from old numbers
l(0,0).
{l(T+1,New) : op(Old,New)} = 1 :- l(T,Old), num(T+1), op(Old,_).
%no number twice
:- 2 #sum {1,T : l(T,Value)}, num(Value).
%2 before 10 before 14
%linear encoding
reached(T,10) :- l(T,10).
reached(T+1,10) :- reached(T,10), num(T+1).
:- reached(T,10), l(T,2).
:- l(T,14), l(T+1,_).
%looks nicer, but quadratic
%:- l(T2,2), l(T10,10), T10<T2.
%:- l(T14,14), l(T10,10), T14<T10.
%we must have these three numbers in the list somewhere
:- not l(_,2).
:- not l(_,10).
:- not l(_,14).
#show r(T,V) : l(T,V).
#show.
Having a slightly more ugly encoding improves grounding a lot (which was your main problem).
I restricted op/2 to not start with 14, as this should be the last element in the list
I do create the list iteratively, this may not be as nice, but at least for the start of the list it already removed impossible to reach values via grounding. So you will never have l(1,33) or l(2,45) etc...
Also list generation stops when reaching the value 14, as no more operation is possible/needed.
I also added a linear scaling version of the "before" section, although it is not really necessary for this short list (but a cool trick in general if you have long lists!) This is called "chaining".
Also note that your show statement is non-trivial and does create some constraints/variables.
I hope this helps, otherwise feel free to ask such questions also on our potassco mailing list ;)
My first attempt is to generate a permutation of numbers and force successor elements to be connected by one of the 3 operations (+5, +7 or sqrt). I predefine the operations to avoid choosing/counting problems. Testing for <60 is not necessary since the output of an operation has to be a number between 0 and 59. The generated List l/2 is forwarded to the output r/2 until the number 14 appears. I guess there is plenty of room to outrun my solution.
num(0..59).
%valid operation pairs
op(N*N,N):- N=2..7.
op(Ori,New):- num(Ori), New = Ori+7, num(New).
op(Ori,New):- num(Ori), New = Ori+5, num(New).
%for each position one number
l(0,0).
{l(T,N):num(N)}==1:-num(T).
{l(T,N):num(T)}==1:-num(N).
% following numbers are connected with an operation until 14
:- l(T,Ori), not op(Ori,New), l(T+1,New), l(End,14), T+1<=End.
% 2 before 10 before 14
:- l(T2,2), l(T10,10), T10<T2.
:- l(T14,14), l(T10,10), T14<T10.
% output
r(T,E):- l(T,E), l(End,14), T<=End.
#show r/2.
first Answer:
r(0,0) r(1,5) r(2,12) r(3,19) r(4,26) r(5,31) r(6,36) r(7,6)
r(8,11) r(9,16) r(10,4) r(11,2) r(12,9) r(13,3) r(14,10) r(15,15)
r(16,20) r(17,25) r(18,30) r(19,37) r(20,42) r(21,49) r(22,7) r(23,14)
There are multiple possible lists with different length.

Calculate maximum number of rooms occupied at once [duplicate]

This question already has answers here:
Given a set of intervals, how to find the maximum number of intersections among them,
(3 answers)
Closed 3 years ago.
On the input, we are given a number N stating how many presentations are to be given, which is followed by N rows of start and end times given in HHMM format
Example:
3
0800 0900
0830 1000
0900 1030
The code must calculate the maximum nuber of occupied rooms (one room can host only one presentation at a time, therefore expected output to the provided example is 2.
My first idea was to create a table of bools 1440 x N (number of minutes in a day by number of presentations) and fill each minute when a presentation is being held, and later go column by column and find the maximum value of presentations at a time. It works, but I'm sure it can be done faster and better. Can someone suggest how to do it in a better manner?
Pretty simple actually: we just simulate the process. First of all, it doesn't matter which presentations are going on right now. All we care about is the number of presentations happening. So we'll just have a counter which we update when a presentation starts or ends.
We could iterate over every minute for the simulation, but our counter only changes when a presentation starts or ends, so we can just make a big list of all the start and end events, sort the list by time, and iterate through the list adjusting our counter appropriately.
The way you propose needs 1440 x 3 = 4320 values. As you can tell, that's very inefficient. A better way is to store just the minutes that are actually required. To save even less values, divide the time into slots of 30 minutes.
Now use a dictionary (std::map) to keep a count of how many presentations are during the same time slot. For your example this gives:
std::map<std::string, int> slots =
{
{"0800", 1},
{"0830", 2},
{"0900", 2},
{"0930", 2},
{"1000", 1},
{"1030", 1},
}
I'll let you figure out how to implement this.

Python, getting a centered average with a catch

So, my assignment is to get the centered average of a list, much like a few of the other posts on here like this one (https://codereview.stackexchange.com/questions/108404/how-to-get-a-centered-mean-excluding-max-and-min-value-of-a-list-in-python) and a few others. However, my professor has told us we are not allowed to use min, max, or sort to solve this. So what I have right now is this, it is still a work in progress:
def centered_average(nums):
high=0
low=0
a=0
b=0
for i in range(len(nums)):
if nums[i]>a:
a=nums[i]
high=a
for i in range(len(nums)):
if nums[i]<b:
b=nums[i]
low=b
total=sum(nums)
average=(total-high-low)/(len(nums)-2)
print(average)
My problem is that I can't get low to be recognized as the lowest number in the list. For example, if I input [1,2,3,4,5] as the list, my function should return 5 as the high, 1 as the low, and 3 as the centered average since 2+3+4 is 9/3=3. However, what I have right there returns the low as 0. I think it is because of the (lens(nums) since it would think the first number is a 0. I'm not sure how I should fix this.
Note: I am still a beginner at this stuff so I know what I have might not be the best or that the error could be simple to fix, but I am still in the process of learning so any help and advice would be much appreciated.
The problem is your starting the running minimum (and running maximum) as 0.
Start the running minimum as float("inf") (as everything is guaranteed to be less than that). Start the running maximum as float("-inf") (as everything is guaranteed to be greater than that).
Or, start both as the first element of the list (which is either a true minimum/maximum, or there's another element that is lower/higher than it).

Sieve of Erathostenes.. find primes in range. How to get starting point?

**NOTE: This is related to a college assignment. I'm only requesting some guidance in the right direction.
I have a single threaded solution to find prime numbers (Homework is to convert to multi threaded solution). It currently says to start off with the list of numbers to be checked. Starting with the first prime, 2. (for 0...N).
I want to be able to divide up the list (0...N) to something like (0...25), (26...50), (51...75) and (76...100).
If the starting point for each list is the first prime. How do I find it? Must I have a seperate function to get that?
Thanks.
I take it that you want a multi-threaded implementation. You don't need each list to start with a prime. (That would actually be a bit circular, considering what you're trying to compute.) Think of a group of workers, each with a list. Rather than have each worker work in isolation, think of broadcasting the current prime against which to sieve and have each worker go off and apply it to that worker's list. Wait until every worker reports completion of that phase, find the next prime, and repeat.
To add multithreading, I would just use a variable to keep track of what number the sieve is up to, and start a thread to remove the multiples of those numbers.
int a = 2;
//run thread 1
while(sieve[a] == false)
a++;
//run thread 2
//etc.
Obviously there's a little more to it.. but this is the general idea.

Logical Programming Problem

I've been trying to solve this problem for quite sometime but I am having trouble with it.
Let's say on a trigger, you receive values.
First trigger: You get 1
Second trigger: You get 1, 2
Third trigger: You get 1, 2, 3
So, I store 1.
For 2nd trigger, I store 2 since 1 already exist.
For 3rd trigger, I store 3 since 1,2 already exist
so in total I have stored 1,2,3
As you can see, we can easily check for new values, if old != new.
Here's come the problem:
Fourth trigger: You get 1, 2, 4
For 4th trigger, I store 1, 2 because it exists
but how do I check against 3 and remove 3 from store and check if 4 is new?
If you are having problems understanding this, feel free to clarify. Thanks!
Use a std::set<int> container. When a trigger arrives, clear it an insert all the values from trigger. This should be ok if you work with just a few numbers (about ten or so). With more, a little bit more sophisticated approach might be required.
Hard to tell what you're asking exactly, but see std::set data structure if your main problem is trying to maintain a set of unique numbers and efficiently check for existence in the set.
Your logic changed between 1,2,3 and 1,2,4
(only stored 3 on former, but stored 1,2,4 on latter)
In that case, ignore data recv'd that already exists, only storing new data, unless some old data was not sent in which case you'll create a new set of data to store.
But, I'm guessing that's not what you had in mind at all :)
edit
I see it's been edited now, so my answer is invalid
edit-2
the fastest way is to drop all stored data on each iteration as comparisons will take as long (if not longer) than a complete save of sent data.
Your approach sounds like it is better served by using some basic set theory. A couple of answers already point you to STL sets for that matter. With that, you'll need to iterate through the reported values to test for membership in the set.
However, is there an opportunity to affect what is reported with each "trigger"? For example, if this is something like a select poll, you could just put whatever it is that you're polling into a different state so that it is not reported as ready in subsequent triggers.