Point-of-sale scanning API [closed] - algorithm

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Consider a store where items have prices per unit but also volume
prices. For example, apples may be $1.00 each or 4 for $3.00.
Implement a point-of-sale scanning API that accepts an arbitrary
ordering of products (similar to what would happen at a checkout line)
and then returns the correct total price for an entire shopping cart
based on the per unit prices or the volume prices as applicable.
Here are the products listed by code and the prices to use (there is
no sales tax):
Product Code | Price
A | $2.00 each or 4 for $7.00
B | $12.00
C | $1.25 or $6 for a six pack
D | $0.15
There should be a top level point of sale terminal service object that looks
something like the pseudo-code below. You are free to design and
implement the rest of the code however you wish, including how you
specify the prices in the system:
terminal.setPricing(...) terminal.scan("A") terminal.scan("C") ...
etc. result = terminal.total
Here are the minimal inputs you should use for your test cases. These
test cases must be shown to work in your program:
Scan these items in this order: ABCDABAA; Verify the total price is
$32.40. Scan these items in this order: CCCCCCC; Verify the total
price is $7.25. Scan these items in this order: ABCD; Verify the total
price is $15.40.

1) For each item store the unit price, the group price and the units per group.
2) During the scanning phase simply keep track of the number of units per item.
3) For each item, increment the cost by:
(number units) / (units per group for item) * group price +
(number units) % (units per group for item) * unit price
A linear amount of space is used on the order of the number of items and a linear amount used to track the counts of the items scanned. Runtime is also linear.
You can implement In PHP : test.php
<?php
echo "Please input the product code string:";
$handle = fopen ("php://stdin","r");
$line = fgets($handle);
echo 'input : ' .$line. "n";
$inputProducts = rtrim($line);
$total = 0;
$inputArray = str_split($inputProducts, 1);
$counts = array_count_values($inputArray);
$productsprice = array('A'=>array('1'=>2.00, '4'=>7.00), 'B'=>array('1'=>12.00), 'C'=>array('1'=>1.25, '6'=>6.00), 'D'=>array('1'=>0.15));
foreach($counts as $code=>$amount) {
echo "Code : " . $code . "n";
if(isset($productsprice[$code]) && count($productsprice[$code]) > 1) {
$groupUnit = max(array_keys($productsprice[$code]));
$subtotal = intval($amount / $groupUnit) * $productsprice[$code][$groupUnit] + fmod($amount, $groupUnit) * $productsprice[$code]['1'];
$total += $subtotal;
}
elseif (isset($productsprice[$code])) {
$subtotal = $amount * $productsprice[$code]['1'];
$total += $subtotal;
}
echo "Subtotal: " . $subtotal . "n";
}
echo 'Final Total: $' . number_format($total, 2). "n";
?>
Execute CLI: php test.php

Related

Sort shopping list based on previous shopping trips

I want to sort a shopping list based on the order items were checked off in previous shopping trips. For example I go to the store and shop Apples, Bananas and Eggs.
Next I go to the store I shop Avocados and Tomatos and Apples. For my next trip the application sorts Avocados, Tomatos and Apples all before Eggs f.e.
I found this post talking about topological sorting: How to sort a shopping list based on previous pick order?.
However I am not sure how this should work since in theory I could have cycles (A user could theoretically check off apples and then bananas and the next time bananas are checked off before apples).
Could you guide me on how to tackle this problem?
Kind regards
I assume:
Past item orderings should guide ordering the current order.
Any new items appear after any items ordered historically.
Orderings further back in time should have less impact than more recent orderings.
My idea is to assign weights to items seen in past orders based on:
Their position in a historic ordering.
How old that odering is.
The weightings might need adjusting, but, using data from that other question you link to, the Python code below does create orderings based on historic orderings:
from collections import defaultdict
shop = [['Toothpaste', 'Bread', 'Meat', 'Vegetables', 'Milk', 'Ice cream'], # last
['CDs', 'Bread', 'Fruit', 'Vegetables', 'Juice', 'Sugar', 'Chocolates'], # last-but-1
['Meat', 'Juice', 'Milk', 'Sugar']] # last-but-2
def weight_from_index(idx: int) -> float | int:
"Items to the left are of LOwer wt and will sort first."
return idx + 1
def historic_multiplier(idy: int) -> float:
"Older rows have larger multipliers and so are of lower overall weight."
return (idy + 1)**1
def shopping_weights(history: list[list[str]]) -> dict[str, int | float]:
"Weight for items from historic shops."
item2weight = defaultdict(float)
for y, hist in enumerate(history):
for x, item in enumerate(hist):
item2weight[item] += historic_multiplier(y) * weight_from_index(x)
return dict(item2weight)
def order_items(items: list[str], weights) -> list[str]:
wts = weights.copy()
new_items = set(items) - set(wts)
# New items last, but in given order otherwise
max_wt = max(wts.values())
for itm in new_items:
wts[itm] = max_wt + 1 + items.index(itm)
return sorted(items, key = lambda i: wts[i])
item_weights = shopping_weights(shop)
new_shop = ['Curry', 'Vegetables', 'Eggs', 'Milk', 'CDs', 'Meat']
new_order = order_items(new_shop, item_weights)
print(new_order)
# ['CDs', 'Meat', 'Vegetables', 'Milk', 'Curry', 'Eggs']
# Update the historic item orders
shop.insert(0, new_order)

Auto Increment ID in SQL [duplicate]

This question already has answers here:
Auto Increment after delete in MySQL
(18 answers)
Closed 12 months ago.
I want to know how can I make my SQL Database table give an ID starting from 0 and with every new add to check if there is an old ID free .
Exemple :
I added 10 items then I deleted almost everyone and I kept item with ID=5.
After adding a new item , it gets id 11 not 0.
Note : I'm editing my DB with Laravel API.
SQL AUTO INCREMENT adds 1 to the biggest incrementable column value.
To fill a free integer slot you need to check for it manually, but that kinda defeats the purpose of auto-incrementing.
Anyway here is how to check for the first free ID value:
function getUnusedId($ids_array)
{
$max_id = max($used_ids); // can be 25 for example
// [1:(id|1), 2:(id|2), 3:(id|3), 4:(id|5)] =>> ID 4 is missing
for($i = 1; $i <= $max_id; $i++){
if($used_ids[$i] > $i){
return $i;
}
}
return $max_id + 1; // You can echo that all IDs are used.
}
// The IDs must be ordered for this solution
$used_ids = Model::orderBy('id')->pluck('id')->toArray();
$free_id = getUnusedId($used_ids);

How to manage the number of loops in while loop Pseudocode

I'm a beginner and wanna ask about While Loop Pseudocode for the number of loops if i want it to be entered by user and not specifying how many, should i write it like this? or i have to declare the SM first?
Thank you
BEGIN
Student = 0
WHILE Student < SM
Get Work Efficiency, Task Completion Effectiveness, Team Work, SM # SM is
the number of students’ marks to be entered
Sum = Work Efficiency + Task Completion Effectiveness + Team Work
Competency = (Sum / 50) * 100
If Competency >= 70%
grade = ‘A’
display = “Exceed Expectation!”
else if Competency >= 40% AND Competency < 70%
grade = ‘B’
display = “Meet Expectation”
else if Competency >= 0% AND Competency < 40%
grade = ‘C’
display = “Below Expectation”
else
display = “Invalid input”
End if
Student = Student + 1
END WHILE
END
As you say, SM is provided by user's input, thus you should mention it somewhere. There is a lot of various ways of writing pseudocode and they mostly depend from your needs, so you could e.g. write:
SM <- integer user input
[rest of your code]
or wrap it in a function (that way you show that returned value is dependent from SM's value:
function foo(SM):
[rest of your code]

How to calculate original loan amount without year terms?

https://www.moneysmart.gov.au/tools-and-resources/calculators-and-apps/savings-goals-calculator
I want to get result like above calculator when I select:
I want to save: 6000
I want to spend it: As soon as possible
Starting balance: 0
Interest rate : 10%
Regular savings: 1000 Monthly
But I am getting not correct result using this code:
loan = 6000.0
interest = 10.0
monthly_payment = 1000.0
i =0.0
record = []
count = 1
add_interst = 0.0
while( loan>=0)
i = interest/(100*12)*loan
loan=i+(loan)-(monthly_payment);
add_interst = add_interst + i
end
puts add_interst
I am getting 181.42163384701658 which should be 168. I don't know where I am wrong.
The code doesn't work because you are doing the opposite of what the link you reference is doing. What they are calculating is saving interest, what you are calculating is loan interest.
Basically, this is how you should define the variables.Also, as others have pointed out, it is good to use BigDecimal to calculate money:
require 'bigdecimal'
balance = 0.to_d
interest = 10.to_d/1200.to_d
regular_saving = 1000;
goal =6000;
i = 0;
added_interest = 0
So, to correct things, you have to start from the starting balance (i.e 0) and start incrementing. Something like this:
while balance < goal
balance += regular_saving;
i = balance * (interest);
balance +=i;
added_interest+=i;
end
Note also, that in the last year you don't need to pay the full saving amount. You only need to pay to reach the goal. For that, you need to add a conditional statement to check goal - balance < regular_saving. If this was the case, the interest should be calculated in terms of the balance that should be paid (slightly less than the goal).

Amazon interview: Timestamp sorting: Find the three page subset sequence repeated maximum number of times [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
The Amazon interview question is:
Given a log file containing (User_Id, URL, Timestamp) user can navigate page from one to the other. Find the three page subset sequence repeated maximum number of times. Records are sorted by Timestamp.
I found this question from this reddit thread.
The poster wrote:
"Given a log file containing (User_Id, URL, Timestamp) user can navigate page from one to the other. Find the three page subset sequence repeated maximum number of times. Records are sorted by Timestamp."
(Although, I wasn't told until late in the interview the file is sorted by timestamp. One of the first things I had asked was if the log was sorted, and my interviewer said no.)
I do think I gave it my all -- I seemed to have been on the right track using a hashmap. I always let my interview know what I was thinking and gave possible outcomes, time complexities, etc.
I am not sure how to approach this problem. What does "Find the three page subset sequence repeated maximum number of times" mean? And if the question didn't say "Records are sorted by Timestamp" (as happened to the poster), then how would that affect the problem?
With "three page subset sequence" I am guessing they mean the three pages must be next to each other, but their internal order does not matter. (A B C = C A B)
public Tuple<string,string,string> GetMostFrequentTriplet(
IEnumerable<LogEntry> entries,
TimeSpan? maxSeparation = null)
{
// Assuming 'entries' is already ordered by timestamp
// Store the last two URLs for each user
var lastTwoUrls = new Dictionary<int,Tuple<string,string,DateTime>>();
// Count the number of occurences of each triplet of URLs
var counters = new Dictionary<Tuple<string,string,string>,int>();
foreach (var entry in entries)
{
Tuple<string,string,DateTime> lastTwo;
if (!lastTwoUrls.TryGetValue(entry.UserId, out lastTwo))
{
// No previous URLs
lastTwoUrls[entry.UserId] = Tuple.Create((string) null, entry.Url, entry.Timestamp);
}
// (comparison with null => false)
else if (entry.Timestamp - lastTwo.Item3 > maxSeparation) {
// Treat a longer separation than maxSeparation as two different sessions.
lastTwoUrls[entry.UserId] = Tuple.Create((string) null, entry.Url, entry.Timestamp);
}
else
{
// One or two previous URLs
if (lastTwo.Item1 != null)
{
// Two previous URLs; Three with this one.
// Sort the three URLs, so that their internal order won't matter
var urls = new List<string> { lastTwo.Item1, lastTwo.Item2, entry.Url };
urls.Sort();
var key = Tuple.Create(urls[0], urls[1], urls[2]);
// Increment count
int count;
counters.TryGetValue(key, out count); // sets to 0 if not found
counters[key] = count + 1;
}
// Shift in the new value, discarding the oldest one.
lastTwoUrls[entry.UserId] = Tuple.Create(lastTwo.Item2, entry.Url, entry.Timestamp);
}
}
Tuple<string,string,string> maxKey = null;
int maxCount = 0;
// Find the key with the maximum count
foreach (var pair in counters)
{
if (maxKey == null || pair.Value > maxCount)
{
maxKey = pair.Key;
maxCount = pair.Value;
}
}
return maxKey;
}
The code goes over the log entries and separates the stream for each user. For each three consecutive URLs for any user, we increment the count for that triplet. Since the order of the three pages are not important, we reorder them in a consistent way, by sorting. In the end, we return the triplet that has the highest count.
Since we only need the last three URLs for each user, we only store the previous two. Combined with the current URL, that makes the triplet we need.
For n URLs, m unique URLs, u users, and s single-visit users, the method will do 2 n - 2 u + s (= O(n)) dictionary lookups, and store up to C(m,3) + u (= O(m3 + u)) tuples.
Edit:
Infer sessions by the duration between requests. If they differ by more than maxSeparation, the new request is treated as the first from that user.

Resources