Advertisement
YaroslavPodorvanov

Untitled

Feb 19th, 2019
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function assert(n: number) {
  2.     if (n > 0) {
  3.         return;
  4.     }
  5.  
  6.     throw new Error("must be positive");
  7. }
  8.  
  9. class PriceRange {
  10.     public readonly range: number;
  11.  
  12.     constructor(public readonly min: number,
  13.                 public readonly max: number,
  14.                 public readonly weight: number,) {
  15.         assert(min);
  16.         assert(max);
  17.         assert(weight);
  18.  
  19.         if (min > max) {
  20.             throw new Error(`"from" must be more than "to"`);
  21.         }
  22.  
  23.         this.range = this.max - this.min;
  24.     }
  25.  
  26.     public minAmount() {
  27.         return this.weight * this.min;
  28.     }
  29.  
  30.     public maxAmount() {
  31.         return this.weight * this.max;
  32.     }
  33. }
  34.  
  35. class Result {
  36.     constructor(public readonly prices: Array<number>,
  37.                 public readonly found: boolean,) {
  38.     }
  39. }
  40.  
  41. function min(priceRangeList: Array<PriceRange>): number {
  42.     let result = 0;
  43.  
  44.     for (let i = 0; i < priceRangeList.length; i++) {
  45.         result += priceRangeList[i].minAmount();
  46.     }
  47.  
  48.     return result;
  49. }
  50.  
  51. function max(priceRangeList: Array<PriceRange>): number {
  52.     let result = 0;
  53.  
  54.     for (let i = 0; i < priceRangeList.length; i++) {
  55.         result += priceRangeList[i].maxAmount();
  56.     }
  57.  
  58.     return result;
  59. }
  60.  
  61. function find(totalAmount, priceRangeList: Array<PriceRange>): Result {
  62.     const maxRemain = totalAmount - min(priceRangeList);
  63.     if (maxRemain < 0) {
  64.         return new Result([], false);
  65.     }
  66.  
  67.     const minRemain = totalAmount - max(priceRangeList);
  68.     if (minRemain > 0) {
  69.         return new Result([], false);
  70.     }
  71.  
  72.     let currentRemain = maxRemain;
  73.  
  74.     const prices = [];
  75.     for (let i = 0; i < priceRangeList.length; i++) {
  76.         prices[i] = priceRangeList[i].min;
  77.     }
  78.  
  79.     for (let i = 0; i < priceRangeList.length; i++) {
  80.         const priceRange = priceRangeList[i];
  81.  
  82.         const priceUp = Math.min(Math.floor(currentRemain / priceRange.weight), priceRange.range);
  83.  
  84.         if (priceUp > 0) {
  85.             currentRemain -= priceUp * priceRange.weight;
  86.  
  87.             prices[i] += priceUp;
  88.  
  89.             if (currentRemain === 0) {
  90.                 new Result(prices, true);
  91.             }
  92.         }
  93.     }
  94.  
  95.     return new Result(prices, false);
  96. }
  97.  
  98. function test() {
  99.     try {
  100.         const result = find(
  101.             51106000,
  102.             [
  103.                 new PriceRange(1400, 2070, 11868),
  104.                 new PriceRange(1400, 2070, 6924),
  105.                 new PriceRange(1400, 2070, 6366),
  106.                 new PriceRange(1400, 2070, 2964),
  107.                 new PriceRange(1400, 6000, 300),
  108.             ],
  109.         );
  110.  
  111.         if (result.found) {
  112.             console.log(result.prices);
  113.         } else if (result.prices.length > 0) {
  114.             console.log("only approximate prices", result.prices);
  115.         } else {
  116.             console.log("result not found");
  117.         }
  118.     } catch (e) {
  119.         console.error("invalid data", e);
  120.     }
  121. }
  122.  
  123. test();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement