Fuzzy logic on price calculation - c#-4.0

I am having one price calculation code in C#.There is particular sequence of calculating all the prices and taxes.how to apply fuzzy logic so that I will get related search of that particular price.That means if one of tax name is 'cost/kg'.So I should get all the names of taxes or prices which start from C or CO.

A simple way would be getting prices within some min/max bounds of what has been searched
double k = 0.1;
double min = searchedAmount - (searchedAmount * k);
double max = searchedAmount + (searchedAmount * k);
var results = products.Where(p => p.Price >= min && p.Price <= max);

Related

A function to calculate estimated duration

I would like to know if there is an existing function in Excel (e.g., in finance) to undertake the following task.
Imagine we have planned the sales of a product for 2013 as C5:G6. And we have stock in J10. We want to calculate the estimated number of months the stock can support the sales. For instance, given the stock is 360, it has enough quantity for 100 in January and 200 in February, and there will be 60 left, which will be consumed in 60/300 months, thus the expected return value is 2,2 months.
I have written a long formula in Excel to do so:
= LET(
ps;
C6:G6;
sq;
J10;
cumuls;
SCAN(0; ps; LAMBDA(a; b; a + b));
m;
REDUCE(
0;
cumuls;
LAMBDA(acc; value; IF(value <= sq; acc + 1; acc)));
IFS(
m = 0;
sq / INDEX(ps; 1; 1);
m >= COLUMNS(ps);
m;
TRUE;
(sq - INDEX(cumuls; 1; m)) / INDEX(ps; 1; m + 1) + m))
However, I'm wondering if there is any existing function in Excel for this purpose.
Not sure if this is what you're after, but this formula would spill the result in one go:
=LET(months,TRANSPOSE(C6:G6),
stock,J6:J11,
cml,SCAN(0,months,LAMBDA(a,b,a+b)),
mx,XMATCH(stock,cml,1),
(stock-INDEX(cml,mx))/INDEX(months,mx)+mx)

An internal unit of company XYZ provides services to other departments

Example 1:
``
Given S="300.01" and B-["300.00", "200.00*,*100.00"].
R[0]="150.00" (=300.01 300.00/600.00) R[1]="100.00" (=150.01* 200.00/300.00)
R[2]="50.01" (=50.01*100.00/100.00)
Example 2 (Pay careful attention to this one).
Given S="1.00" and B=["0.05","1.00"]. 1. First we consider 1.00 because it is the largest,
a. 1.00*1.00/1.05~0.95238...
b. Round 0.95238... to "0.95". Rounding down to carry pennies to smaller departments. c. Set R[1]=0.95. Notice, this is in the same place as 1.00. It is the 2nd value in the result! 2. Now we have 0.05 left
Next we look at the smaller B[0]=0.05 department
a. 0.05 0.05/0.05 = 0.05 b. No rounding required
c. Set R[0]=0.05. R=["0.05", "0.95"]
`
Write a function:
class Solution { public String[] solution(String 5, String[] B); }
that, given a string S representing the total excess billables and an array B consisting of K strings representing the undiscounted bills for each customer. The return value should be an array of strings R (length M) in the same order as B representing the amount of the discount to each customer.
Notes:
The total S should be completely refunded. Neither more nor less than S should be
returned. Don't lose or gain a penny!
Be careful with the types you choose to represent currencies. Floating points numbers are notoriously error prone for precise calculations with currencies.
Test Output
Amounts should be rounded down to the nearest $0.01. By design, fractional pennies are pushed to groups with smaller unadjusted invoices.
Results should be represented with 2 decimal places of precision as strings, even if these are both zeroes. ex. "100.00" 5. You may assume sensible inputs. The total to be discounted will never exceed the total of the
unadjusted invoices.
Please do pay attention to returning the discounts in the same order as the incoming invoices.
Answer:::
def solution(A):
answer = 0
current_sum = 0
#Currently there is one empty subarray with sum 0
prefixSumCount = {0:1}
for list_element in A:
current_sum = current_sum + list_element
if current_sum in prefixSumCount:
answer = answer + prefixSumCount[current_sum]
if current_sum not in prefixSumCount:
prefixSumCount[current_sum] = 1
else:
prefixSumCount[current_sum] = prefixSumCount[current_sum] + 1
if answer > 1000000000:
return -1
else:
return answer
#Sample run
A = [2,-2,3,0,4,-7]
print(solution(A))
strong text
Find my solution for JavaScript
You can avoid function sumArray and use the sum funciton with reducer within solution function.
enter code here
function solution(S, B) {
// write your code in JavaScript (Node.js 8.9.4)
let copyArray=[...B];
let solutionObj={};
//ordered array to consider last first
copyArray.sort();
//calculating sum of values within array
let sumArray=B.reduce((acc,value)=> acc+Number(value),0);
//calculating values of array
//loop for ading on to solvin array
let initial=S;
for(i=copyArray.length-1;i>=0;i--){
//obtaining index of value addded to solution array
let index=B.indexOf(copyArray[i]);
let value=initial*copyArray[i]/sumArray;
value=i==0?Math.ceil(value*100)/100:Math.floor(value*100)/100;
solutionObj[index]=value.toFixed(2);
}
return Object.values(solutionObj) ;
}
console.log(solution(300.01,["300.00","200.00","100.00"]))
console.log(solution(1.00,["0.05","1.00"]))
These are the resulting entries
Solution in java for the same coding exercise
public String[] solution(String S, String[] B) {
List<Double> list = Arrays.stream(B).sorted(Comparator.comparingDouble(v->Double.valueOf((String) v)).reversed()).map(Double::parseDouble).collect(Collectors.toList());
Double S1 = Double.valueOf(S);
String R[] = new String[B.length];
Double total = 0.00;
for (int i = 0; i< list.size(); i++){
Double individualValue = list.get(i);
Double sumTotal = 0.0;
for(int j = i+1;j < list.size(); j++){
sumTotal+=list.get(j);
}
BigDecimal data = new BigDecimal(S1 * (individualValue / (individualValue + sumTotal)));
data = data.setScale(2, RoundingMode.FLOOR);
total+=data.doubleValue();
R[i] = String.valueOf(data);
S1 = S1 - Double.valueOf(R[i]);
}
Double diff = new BigDecimal(Double.valueOf(S) - total).setScale(2, RoundingMode.HALF_DOWN).doubleValue();
if (diff > 0) {
R[B.length - 1] = String.valueOf(Double.valueOf(R[B.length - 1]) + diff);
}
return R;
}

Get real-time distance between running cars on Azure Stream Analytics

We will get streaming data of many cars on a particular Stream Analytics. Each row will have vehicleId, latitude and longitude of vehicle. I need to raise an alarm whenever distance between ANY two cars is less than suppose x meters.
Right now we can consider radial distance to keep it simple. Hence, we need to calculate distance of cars NOT from a fix point but from other cars ( near by cars can keep changing with time ). Hence, we cannot hard-code vehicle id in the query for sure.
We do have Geo-spatial functions support https://learn.microsoft.com/en-us/stream-analytics-query/geospatial-functions ..
I am not sure if this can even be done by Stream Analytics query directly.
I created a small example of the potential solution, not perfect one perhaps, but it resolves the problem in the ASA job.
Essentially I have re-used javascript function that expects simple latitude and longitude and gives the distance in meters. You can use potentially the geospatial embedded function - I haven't tried to play with that.
So, idea is to cross join input, for all input messages(unfortunately yes, you get duplicated result but it works), and then you apply distance function and filter to the output only those that have a distance less than a threshold value. The following example propagates to the output only if the distance is not zero(it means it compared with itself) and if it is less than 5 meters:
with inputData as (select * from input i1 inner join input i2 ON DATEDIFF(second,i1,i2) BETWEEN 0 AND 5),
distances as (select *, udf.getGeoDistance(i1.lat,i1.long,i2.lat,i2.long) as distance from inputData)
select *
into output
from distances
where distance <> 0 and distance < 5
UDF function:
// Sample UDF which returns sum of two values.
function getDistanceFromLatLonInKm(lat1, lon1, lat2, lon2) {
'use strict';
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(lat2 - lat1); // deg2rad below
var dLon = deg2rad(lon2 - lon1);
var a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2)
;
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c * 1000; // Distance in m
return d;
}
function deg2rad(deg) {
return deg * (Math.PI / 180);
}
Input:
[
{
"name" : "car1",
"lat" : 59.3293371,
"long" : 13.4877472
},
{
"name" : "car2",
"lat" : 59.293371,
"long" : 13.2619422
},
{
"name" : "car3",
"lat" : 59.3293371,
"long" : 13.4877040
}
]
And result(car1 and car3 are close to each other):
Follow your latest comment,you use tumbling-window and set 5 seconds timeunit to get slice of data.Per my knowledge, you still could not calculate distance of cars each other by sql and Geo-spatial functions directly.Not to mention a warning.
I came up with an idea that you may could use Azure Function as the output of ASA job.Collect the slice of data and send them into Azure Function as json parameter.Inside function,you could write code to calculate the distances between cars each other,even alert warnings to other destinations.

How can I replace automatically-generated grand total values with different ones (Aspose Cells)?

My spreadsheet automatically generates a "Grand Totals" column as the rightmost column:
This is nice, in general. But in specific, I've got a couple of problems with it: The last two values (with the unfortunate labels "Sum of Avg Price" and "Sum of Percentage") provide just that - a sum of the previous columns. In those cases, I don't want a simple sum, but an average in the first case and a percentage in the second case.
For the AvgPrice, what I need is a calculation of "Sum of Total Price" / "Sum of Total Quty" in the Grand Total column. For instance, the first AvgPrice Grand Total value should be "33.14" rather than "66.26"
For the Percentage, I need the percentage of Total Price for the item/Description (such as "25151.75" seen in the first item above) as compared to the "Total Price" value in the "Total Sum of Total Price" grand total row/column ("1529802.82"). That value is seen here:
So the "Percentage" value for that first item ("ASPARAGUS, LARGE 11/1#") should be approximately 1.6 (as 25151.75 is about 1/60th of 1529802.82), rather than 1.36.
Is there a way to set this up to automatically generate those values in the Grand Total Column, or do I need to prevent the Grand Total column from being generated like so:
pivotTable.ColumnGrand = false;
...and then add that column to the sheet manually, doing the calculations in code, and adding those values that way?
In order to look into this issue in detail, please post your query in Aspose.Cells forum with your sample excel files. You can provide us source excel file, actual output excel file and the expected excel file and sample code. And the screenshot like you provided will also be helpful. Thanks for your cooperation in this regard.
Aspose.Cells Forum Link:
https://www.aspose.com/community/forums/aspose.cells-product-family/19/showforum.aspx
Note: I am working as Developer Evangelist at Aspose
It's easiest, I think, to just add that column manually, calculating the necessary values; here's how I'm doing it now (basically the same idea as in Excel Interop - manually adding the Grand Total column):
After the PivotTable code, I call AddManualGrandTotalColumn(), which is:
private void AddManualGrandTotalColumn()
{
var pivot = pivotTableSheet.PivotTables[0];
var dataBodyRange = pivot.DataBodyRange;
int rowsUsed = dataBodyRange.EndRow;
int FIRST_DATA_ROW = 7;
int currentQtyRow = FIRST_DATA_ROW;
int ROWS_IN_A_RANGE = 4;
// Needed?
pivot.RefreshData();
pivot.CalculateData();
// Get Total Sales value, which will be needed for computing the % val
Cell totalTotalPurchasesCell = pivotTableSheet.Cells[rowsUsed - 2, _grandTotalsColumnPivotTable + 1];
decimal totalTotalPurchases = Convert.ToDecimal(totalTotalPurchasesCell.Value);
Cell gtLabelCell = pivotTableSheet.Cells[6, _grandTotalsColumnPivotTable + 2];
gtLabelCell.Value = "Grand Total";
Cell QtyCell = null;
Cell PriceCell = null;
Cell AvgPriceCell = null;
Cell PercentageCell = null;
while (currentQtyRow < rowsUsed)
{
// SumTotalQty
int qty = GetSumTotalQty(currentQtyRow);
QtyCell = pivotTableSheet.Cells[currentQtyRow, _grandTotalsColumnPivotTable + 2];
QtyCell.Value = qty;
// SumTotalPrice
decimal price = GetSumTotalPrice(currentQtyRow+1);
PriceCell = pivotTableSheet.Cells[currentQtyRow+1, _grandTotalsColumnPivotTable + 2];
PriceCell.Value = price;
// Calculate Avg Price (SumTotalPrice / SumTotalQty)
decimal avg = 0.0M;
if ((price > 0) && (qty > 0))
{
avg = price / qty;
}
AvgPriceCell = pivotTableSheet.Cells[currentQtyRow+2, _grandTotalsColumnPivotTable + 2];
AvgPriceCell.Value = avg;
// Calculate Percentage (totalTotalPurchases / SumTotalPrice?)
decimal prcntg = 0.0M;
if ((totalTotalPurchases > 0) && (price > 0)) // ? Right calculation?
{
prcntg = totalTotalPurchases / price;
}
PercentageCell = pivotTableSheet.Cells[currentQtyRow+3, _grandTotalsColumnPivotTable + 2];
PercentageCell.Value = prcntg;
currentQtyRow = currentQtyRow + ROWS_IN_A_RANGE;
}
}
private int GetSumTotalQty(int currentQtyRow)
{
int FIRST_MONTH_COL = 2;
int LAST_MONTH_COL = _grandTotalsColumnPivotTable; // - 1;
int cumulativeQty = 0;
Cell qtyCell = null;
for (int i = FIRST_MONTH_COL; i <= LAST_MONTH_COL; i++)
{
qtyCell = pivotTableSheet.Cells[currentQtyRow, i];
cumulativeQty = cumulativeQty + Convert.ToInt32(qtyCell.Value);
}
return cumulativeQty;
}
. . . (etc. for GetSumTotalPrice())

Billing calculation of rates

Azure Rate Card API returns a MeterRates field (see documentation).
Azure UsageAggregate gives a quantity (see documentation).
According to the azure support page. This is the forum to ask questions.
So, how are meter rates applied?
Example meter rates:
{"0":20, "100":15, "200":10}
If I have a quantity of 175 is the amount 100*20 + 75*15 or 175*15?
Why specify an included quantity?
Example: rates:{"0":23} with included quantitiy 10 could be expressed as rates:
{"0":0, "10":23}
example meter rates: {"0":20, "100":15, "200":10}
if I have a quantity of 175 is the amount 100*20 + 75*15 or 175*15 ?
The pricing is tiered pricing. So when you get the rates it essentially tells you that:
from 0 - 99 units, the unit rate is 20
from 100 - 199 units, the unit rate is 15
from 200 units and above, the unit rate is 10
Based on this logic, your calculation should be:
99 * 20 + 75 * 15 = 3105
One thing which confuses me though is the upper limit. Above calculation is based on the information I received from Azure Billing team. What confused me is what would happen if the consumption is say 99.5 units? For the first 99 units it is fine but I am not sure how the additional 0.5 units will be calculated.
Guarav gets at the core of the issue and is why I marked it as the answer. Based on that I devised the following code to implement the logic. It falls in two parts:
Creating a bucket list from the meter rates
Processing a quantity with the bucket list to determine an amount
The following function creates a list of buckets (each bucket object is a simple POCO with Min, Max and Rate properties). The list is attached to a meter object that has the other properties from the rate card api.
private Dictionary<int, RateBucket> ParseRateBuckets(string rates)
{
dynamic dRates = JsonConvert.DeserializeObject(rates);
var rateContainer = (JContainer)dRates;
var buckets = new Dictionary<int, RateBucket>();
var bucketNumber = 0;
foreach (var jToken in rateContainer.Children())
{
var jProperty = jToken as JProperty;
if (jProperty != null)
{
var bucket = new RateBucket
{
Min = Convert.ToDouble(jProperty.Name),
Rate = Convert.ToDouble(jProperty.Value.ToString())
};
if (bucketNumber > 0)
buckets[bucketNumber - 1].Max = bucket.Min;
buckets.Add(bucketNumber, bucket);
}
bucketNumber++;
}
return buckets;
}
The second function uses the meter object with two useful properties: the bucket list, and the included quantity. According to the rate card documentation (as I read it) you don't start counting billable quantity until after you surpass the included quantity. I'm sure there's some refactoring that could be done here, but the ordered processing of the buckets is the key point.
I think I've addressed issue on the quantity by recognizing that it's a double and not an integer. Therefore the quantity associated with any single bucket is the difference between the bucket max and the bucket min (unless we've only filled a partial bucket).
private double CalculateUsageCost(RateCardMeter meter, double quantity)
{
var amount = 0.0;
quantity -= meter.IncludedQuantity;
if (quantity > 0)
{
for (var i = 0; i < meter.RateBuckets.Count; i++)
{
var bucket = meter.RateBuckets[i];
if (quantity > bucket.Min)
{
if (bucket.Max.HasValue && quantity > bucket.Max)
amount += (bucket.Max.Value - bucket.Min)*bucket.Rate;
else
amount += (quantity - bucket.Min)*bucket.Rate;
}
}
}
return amount;
}
Finally, the documentation is unclear about the time scope for the tiers. If I get a discounted price based on quantity, over what time scope do I aggregate quantity? The usage api allows me to pull data either daily or hourly. I want to pull my data hourly so I can correlate my costs by time of day. But when is it appropriate to actually calculate the bill? Seems like hourly is wrong, daily may work, but it might only be appropriate over the entire month.
Recently I just did this similar task. Following is my example (I think you can use regex to remove those characters rather than like me using replace). The first function parse the rate info string to generate a key-value pair collection, and the second function is used to calculate the total price.
private Dictionary<float, double> GetRatesDetail(string r)
{
Dictionary<float, double> pairs = null;
if(string.IsNullOrEmpty(r) || r.Length <=2)
{
pairs = new Dictionary<float, double>();
pairs.Add(0, 0);
}
else
{
pairs = r.Replace("{", "").Replace("}", "").Split(',')
.Select(value => value.Split(':'))
.ToDictionary(pair => float.Parse(pair[0].Replace("\"", "")), pair => double.Parse(pair[1]));
}
return pairs;
}
public decimal Process(Dictionary<float, double> rates, decimal quantity)
{
double ret = 0;
foreach (int key in rates.Keys.OrderByDescending(k => k))
{
if (quantity >= key)
{
ret += ((double)quantity - key) * rates[key];
quantity = key;
}
}
return (decimal)ret;
}

Resources