Background
In France, and probably in the rest of the European Union, any food available for sale must list the ingredients that compose it on its packaging, in weight percentage descending order. However, the exact percentage doesn't have to be indicated, unless the ingredient is highlighted by the text or an image on the covering.
For example, my basil tomato sauce, showing only some big red tomatoes and beautiful basil leaves on its packaging, has the following indications:
Ingredients: Tomatoes 80%, onions in pieces, basil 1.4%, sea salt, mashed garlic, raw cane sugar, extra virgin olive oil, black pepper.
It sounds savoury, but… how much onions will I eat, exactly?
Challenge
Given a list of weight percentages in descending order, eventually incomplete, output a complete list of the minimal and maximal weight percentages that can possibly be found in the recipe.
- You can write either a function, or a full program.
- The input can be in any reasonable form (array of numbers or list of strings, for instance). Fractional values should be supported at least to one decimal place. A missing weight percentage can be represented in any consistent and unambiguous way (
0
,'?'
ornull
, for instance). You can assume that the input will always be associated to a valid recipe ([70]
and[∅, ∅, 50]
are invalid, for instance). - The output can be in any reasonable form (one array for both of the minimal and maximal weight percentages, or a single list of doublets, for instance). The minimal and maximal percentages can be in any order (
[min, max]
and[max, min]
are both acceptable). Exact weight percentages don't need to be processed differently than other percentages and may be represented by equal minimal and maximal values.
Standard rules for code-golf apply: while you're typing your code, my pasta dish is cooling down, so the shortest submission wins.
Examples
Since this problem is harder than it may look at first glance, here is a step-by-step resolution of a few cases.
[40, ∅, ∅]
Let's call respectively x
and y
the two missing percentages.
- Because it comes after the first ingredient at 40%,
x
can't be higher than 40 % itself.[40, [?, 40], [?, ?]]
- The sum of the two missing percentages is always 60%. Consequently :
- If
x
takes its maximal value, theny
takes its minimal value, which is therefore 60% - 40% = 20%.[40, [?, 40], [20, ?]]
- If
x
takes its minimal value, theny
takes its maximal value. Butx
can't be lower thany
, so in this case,x
=y
= 60% / 2 = 30%.[40, [30, 40], [20, 30]]
- If
[70, ∅, ∅, 5, ∅]
Let's call respectively x
, y
and z
the three missing percentages.
- The minimal and maximal percentages for
z
are necessarily between 0% and 5%. Let's assumez
= 0% for a moment. The sum of the two missing percentages is always 25%. Consequently :[70, [?, ?], [?, ?], 5, [0, 5]]
- If
y
takes its minimal value, 5%, thenx
takes its maximal value, which is therefore 25% - 5% = 20%.[70, [?, 20], [5, ?], 5, [0, 5]]
- If
y
takes its maximal value, thenx
takes its minimal value. Butx
can't be lower thany
, so in this case,x
=y
= 25% / 2 = 12.5%.[70, [12.5, 20], [5, 12.5], 5, [0, 5]]
- If
- Let's verify that everything is fine if we assume now that
z
= 5%. The sum of the two missing percentages is always 20%. Consequently :- If
y
takes its minimal value, 5%, thenx
takes its maximal value, which is therefore 20% - 5% = 15%. This case is already included in the previously calculated ranges. - If
y
takes its maximal value, thenx
takes its minimal value. Butx
can't be lower thany
, so in this case,x
=y
= 20% / 2 = 10%. This case is already included in the previously calculated range fory
, but not forx
.[70, [10, 20], [5, 12.5], 5, [0, 5]]
- If
Test cases
Input: [∅]
Output: [100]
Input: [70, 30]
Output: [70, 30]
Input: [70, ∅, ∅]
Output: [70, [15, 30], [0, 15]]
Input: [40, ∅, ∅]
Output: [40, [30, 40], [20, 30]]
Input: [∅, ∅, 10]
Output: [[45, 80], [10, 45], 10]
Input: [70, ∅, ∅, ∅]
Output: [70, [10, 30], [0, 15], [0, 10]]
Input: [70, ∅, ∅, 5, ∅]
Output: [70, [10, 20], [5, 12.5], 5, [0, 5]]
Input: [30, ∅, ∅, ∅, 10, ∅, ∅, 5, ∅, ∅]
Output: [30, [10, 25], [10, 17.5], [10, 15], 10, [5, 10], [5, 10], 5, [0, 5], [0, 5]]
[40, ∅, ∅]
and[70, ∅, ∅, 5, ∅]
to make things a bit more clearly. A challenge should be clear without looking at the test cases, which isn't the case right now. If I understand it correctly for[40, ∅, ∅]
: 60 more is necessary for 100%, divided over these two∅
. The first∅
has to be 30 or higher (otherwise the second∅
will be above it, which shouldn't be possible when they are in order). In addition, it cannot be above40
, so the first∅
becomes[30,40]
, and the second becomes[(100-40-40=)20, (100-40-30=)30]
. \$\endgroup\$[min,max]
/[max,min]
or mixed allowed? \$\endgroup\$[min,max]
and[max,min]
is borderline acceptable, but since it can't lead to ambiguous results, I'd say it's okay. \$\endgroup\$[70, 12, 11, 5, 2]
not work for your second example? If it does work, the minimum forx
would be less than12.5
. \$\endgroup\$