No, no, there's a much better way.

NB. x is output, y is input, result is fifo allocation
fifo =: 4 : 0
NB. Convert to running sum
outs =: +/\ x
ins =: +/\ y
NB. Interleave in & out to give the unique intervals
uniq =: ~. /:~ ins , outs
NB. Look up each interval in input & output, append length
(outs I. uniq) ,. (ins I. uniq) ,. (2 -~/\ 0,uniq)
)

    out fifo in
0 0  500
1 0  500
1 1 2000
1 2  500
2 2 1000
3 3 1000

Notice that this shows the amount left over at the end.

Henry Rich

Henry Rich wrote:
> Here's an array-oriented approach.
> 
> The key idea is to convert the list of quantities to a running total, so 
> that each input and output is identified uniquely in the stream of results.
> 
>     in =: 1000 2000 1500 1000
>     out =: 500 3000 1000
>     ]ins =: 0 , +/\ in
> 0 1000 3000 4500 5500
>     ]outs =: 0 , +/\ out
> 0 500 3500 4500
> 
> Now we can write a verb that takes an interval representing one output 
> and looks up in the list representing all the inputs, to find which 
> inputs correspond to that output:
> 
> NB. x is low#, high#, y is list of #s, result is table of
> NB. (intvl in y), (amount allocated to intvl)
> fifo1 =: ([: ((] ,. {~)  I.@:*) 2 -~/\ {:@[ <. {...@[ >. ])"1
> 
> The <. and >. have the effect of excluding all the intervals that don't 
> apply, and then it's just a matter of converting the nonempty intervals 
> to the desired output format.
> 
>     0 500 fifo1 ins
> 0 500
>     500 3500 fifo1 ins
> 0  500
> 1 2000
> 2  500
>     3500 4500 fifo1 ins
> 2 1000
> 
> To do all the calculations, just apply fifo1 on each interval of outputs:
> 
> NB. x is list of outputs, y is list of inputs
> NB. Convert each to running total, then allocate each output
> NB. among the correct inputs.  Then, prepend the number of
> NB. the output to give a table of
> NB. output-intvl input-intvl amount
> fifo =: [: ; i...@#@[ ,.&.> (2&(]\)@[ <@fifo1 ])&(0 , +/\)
> 
>     out fifo in
> 0 0  500
> 1 0  500
> 1 1 2000
> 1 2  500
> 2 2 1000
> 
> WARNING!! This two-liner is not ready for production.  It runs in time 
> O(*:n).  But I think it would be easy to bring to O((*^.)n) by adding a 
> step where, after converting the lists to running sums, you use
> 
> (inputs I. outputs)
> 
> to reduce the number of inputs you have to examine for each output; then 
> run fifo1 on the reduced set and add the starting index back into the 
> result.  Details left to the motivated.
> 
> Henry Rich
> 
> 
> bill lam wrote:
>> I want to calculate a fifo problems to match in-qty to out-qty, 
>>
>> Assuming all qty are positive
>> in-qty  1000 2000 1500 1000
>> out-qty  500 3000 1000
>> then a verb fifo, such that
>>
>> 500 3000 1000 fifo 1000 2000 1500 1000
>>
>> will give
>>
>> 0 0  500
>> 1 0  500
>> 1 1 2000
>> 1 2  500
>> 2 2 1000
>>
>> where format in each row, 
>> index-to-outqty   index-to-inqty   qty-allocated
>>
>> I have written a simple scalar C algorithm below and want to learn how to do 
>> it
>> in vector J approach.
>>
>> fifo=: 4 : 0
>> out=. x
>> in=. y
>> ox=. ix=. 0 [ z=. 0 3$0
>> while. (ox<#out) *. ix<#in do.
>>   a=. ox{out
>>   b=. ix{in
>>   if. a=b do.
>>     z=. z, ox, ix, a
>>     out=. 0 ox}out
>>     in=. 0 ix}in
>>     ox=. >:ox [ ix=. >:ix
>>   elseif. a<b do.
>>     z=. z, ox, ix, a
>>     out=. 0 ox}out
>>     in=. (b-a) ix}in
>>     ox=. >:ox
>>   elseif. a>b do.
>>     z=. z, ox, ix, b
>>     out=. (a-b) ox}out
>>     in=. 0 ix}in
>>     ix=. >:ix
>>   end.
>> end.
>> z
>> )
>>
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
> 
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to