# Inventory sequence

Inventory sequence is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

To build the inventory sequence, first take inventory of what numbers are already in the sequence, then, starting with 0 add the count of each number in turn to the end of the sequence. When you reach a number that has a count of 0, stop, add the 0 to the end of the sequence, and then restart the inventory from 0.

E.G.
Start taking inventory; how many 0s are there? 0. Add a 0 to the end of the sequence and restart the inventory. (0)
How many 0s are there? 1. Add a 1 to the end of the sequence. How many 1s are there? 1. Add a 1 to the end of the sequence. How many 2s are there? 0. Add a 0 to the end of the sequence and restart the inventory. (0 1 1 0)
and so on.

• Find and display the first 100 elements of the sequence.
• Find and display the position and value of the first element greater than or equal to 1000.

Stretch
• Find and display the position and value of the first element greater than or equal to 2000, 3000 ... 10,000.
• Plot a graph of the first 10,000 elements of the sequence.

## FreeBASIC

```Dim As Integer max = 10000
Dim As Integer inv()
Dim As Integer counts(max + 100)
counts(0) = 1
Dim As Integer lower = 100
Dim As Integer upper = 1000
Dim As Boolean done = False
Dim As Integer ix = 0
While Not done
Dim As Integer i = 0, c = 0
Do
Dim As Integer j = counts(i)
If Ubound(inv) < max Then
Redim Preserve inv(ix+1)
inv(ix+1) = j
End If
counts(j) += 1
ix += 1
If Ubound(inv) >= lower Then
Print "Inventory sequence, first 100 elements:"
For c = 0 To 99
Print Using "###"; inv(c);
If (c+1) Mod 20 = 0 Then Print
Next
lower = max + 1
End If
If j = 0 Then Exit Do
If j >= upper Then
Print Using !"\nFirst element >= ##,### is ##,### at index ###,###"; upper; j; ix;
If j >= max Then done = True: Exit Do
upper += 1000
End If
i += 1
Loop
Wend

Sleep
```

## J

```   nextinv=:  ((*@] * 1+{.@[), }.@[ , ]) +/@({. = }.)

10 10\$}.nextinv^:100]0   NB. first 100 elements of inventory sequence
0  1  1  0  2  2  2  0  3  2
4  1  1  0  4  4  4  1  4  0
5  5  4  1  6  2  1  0  6  7
5  1  6  3  3  1  0  7  9  5
3  6  4  4  2  0  8  9  6  4
9  4  5  2  1  3  0  9 10  7
5 10  6  6  3  1  4  2  0 10
11  8  6 11  6  9  3  2  5  3
2  0 11 11 10  8 11  7  9  4
3  6  4  5  0 12 11 10  9 13
({:,_2+#)nextinv^:(1000>{:)^:_]0   NB. first value of at least 1000 and its index
1001 24255
```

The inventory sequence has a "hidden value" which is the number that we are searching for, and counting. So, here, we include it as the first element of the representation of an inventory subsequence. And `nextinv` calculates both the next "hidden value" as well as the corresponding subsequence which incorporates a count of how many times the current "hidden value" appeared.

For the task, we iterate inductively from the initial state (either a 100 times or until we find a value which is greater than 1000).

It would be more efficient to maintain counts of each integer so far encountered, but that efficiency is not necessary for this task (and would require more code).

That said, here's a faster implementation:

```invseq=: {{
cnt=. 0, seq=. i. nxt=. 0
while. -. u seq do.
k=. nxt{cnt
nxt=. (*k)*nxt+1
cnt=. (1+k{cnt) k} cnt=. cnt {.~ (2+k)>.#cnt
seq=. seq, k
end.
}}
```
```   stretch=: }.nextinv^:(10000>{:)^:_]0    NB. or
stretch=: (1e4<:{:) invseq   NB. equivalent, faster approach

(,~ {&stretch) {.I.2000<stretch   NB. first value greater than 2000 and its index
2009 43301
(,~ {&stretch) {.I.3000<stretch
3001 61708
(,~ {&stretch) {.I.4000<stretch
4003 81456
(,~ {&stretch) {.I.5000<stretch
5021 98704
(,~ {&stretch) {.I.6000<stretch
6009 121342
(,~ {&stretch) {.I.7000<stretch
7035 151756
(,~ {&stretch) {.I.8000<stretch
8036 168804
(,~ {&stretch) {.I.9000<stretch
9014 184428
(,~ {&stretch) {.I.10000<stretch
10007 201788
require'plot'
plot 1e4{.stretch
```

## jq

Works with both jq and gojq, the C and Go implementations of jq

... but note that gojq takes about 5 times longer (and requires much more memory) to complete the task.

With minor modifications, the program below also works quite snappily with jaq, the Rust implementation of jq.

The definition of `_nwise` can be omitted if using the C implementation of jq.

```def _nwise(\$n):
def n: if length <= \$n then . else .[0:\$n] , (.[\$n:] | n) end;
n;

# Emit the inventory sequence ad infinitum
def inventory_sequence:
{num: 0,
emit: 0,
inventory: {} }
| foreach range(0; infinite) as \$n (.;
.emit = (.inventory[.num|tostring] // 0)
| if .emit == 0 then .num = 0 else .num += 1 end
| .inventory[.emit|tostring] += 1 )
| .emit ;

# Report on the progress of an arbitrary sequence, indefinitely
# Emit [.next, \$x, .n]
def probe(s; \$gap):
foreach s as \$x ({n: 0, next: \$gap};
.n += 1
| if \$x >= .next then .emit = {next, \$x, n} | .next += \$gap
else .emit = null
end)
| select(.emit).emit;

def lpad(\$len): tostring | (\$len - length) as \$l | (" " * \$l)[:\$l] + .;

[limit(\$n; inventory_sequence)] | _nwise(10) | map(lpad(3)) | join(" ");

"",
(limit(10; probe(inventory_sequence; 1000))
| "First element >= \(.next) is \(.x) at index \(.n - 1)")```
Output:
```  0   1   1   0   2   2   2   0   3   2
4   1   1   0   4   4   4   1   4   0
5   5   4   1   6   2   1   0   6   7
5   1   6   3   3   1   0   7   9   5
3   6   4   4   2   0   8   9   6   4
9   4   5   2   1   3   0   9  10   7
5  10   6   6   3   1   4   2   0  10
11   8   6  11   6   9   3   2   5   3
2   0  11  11  10   8  11   7   9   4
3   6   4   5   0  12  11  10   9  13

First element >= 1000 is 1001 at index 24255
First element >= 2000 is 2009 at index 43301
First element >= 3000 is 3001 at index 61708
First element >= 4000 is 4003 at index 81456
First element >= 5000 is 5021 at index 98704
First element >= 6000 is 6009 at index 121342
First element >= 7000 is 7035 at index 151756
First element >= 8000 is 8036 at index 168804
First element >= 9000 is 9014 at index 184428
First element >= 10000 is 10007 at index 201788
```

## Julia

```""" rosettacode.org/wiki/Inventory_sequence """

using Printf
using Counters
using Plots

struct InventorySequence
inventory::Counter{Int}
InventorySequence() = new(counter())
end

function Base.iterate(i::InventorySequence, num = 0)
nextval = i.inventory[num]
num = nextval == 0 ? 0 : num + 1
i.inventory[nextval] += 1
return nextval, num
end

const thresholds = [1000 * j for j in 1:10]
const toplot = Int[]

for (i, n) in enumerate(InventorySequence())
if i <= 100
print(rpad(n, 4), i % 20 == 0 ? "\n" : "")
elseif n >= thresholds[begin]
@printf("First element >= %d5: %d5 in position %d.\n", popfirst!(thresholds), n, i)
length(thresholds) == 0 && break
end
length(toplot) < 10000 && push!(toplot, n)
end

plot(toplot)
```
Output:
Similar to Python output.

## Nim

```import std/[strformat, tables]
import gnuplot

iterator inventorySequence(): (int, int) =
var counts: CountTable[int]
var idx = -1
while true:
var i = 0
while true:
let n = counts[i]
inc idx
counts.inc(n)
yield (idx, n)
if n == 0: break
inc i

echo "First 100 elements:"
var x, y: seq[int]
var lim = 1000
for idx, n in inventorySequence():
if idx < 10000:
if idx <= 100:
stdout.write &"{n:>2}"
stdout.write if idx mod 10 == 0: '\n' else: ' '
if idx == 100: echo()
elif n >= lim:
echo &"First element ⩾ {lim:>5} is {n:>5} at index {idx:>6}"
lim += 1000
if lim > 10000: break

withGnuPlot:
plot(x, y, "Inventory sequence", "with impulses lw 0.5")
png("inventory_sequence.png")
```
Output:
```First 100 elements:
0
1  1  0  2  2  2  0  3  2  4
1  1  0  4  4  4  1  4  0  5
5  4  1  6  2  1  0  6  7  5
1  6  3  3  1  0  7  9  5  3
6  4  4  2  0  8  9  6  4  9
4  5  2  1  3  0  9 10  7  5
10  6  6  3  1  4  2  0 10 11
8  6 11  6  9  3  2  5  3  2
0 11 11 10  8 11  7  9  4  3
6  4  5  0 12 11 10  9 13  8

First element ⩾  1000 is  1001 at index  24255
First element ⩾  2000 is  2009 at index  43301
First element ⩾  3000 is  3001 at index  61708
First element ⩾  4000 is  4003 at index  81456
First element ⩾  5000 is  5021 at index  98704
First element ⩾  6000 is  6009 at index 121342
First element ⩾  7000 is  7035 at index 151756
First element ⩾  8000 is  8036 at index 168804
First element ⩾  9000 is  9014 at index 184428
First element ⩾ 10000 is 10007 at index 201788
```

## Phix

```-- demo\rosetta\Inventory_sequence.exw
with javascript_semantics
function inventory(integer limit)
sequence inv = {0}, counts = {1}
integer ix = 0, thousands = 1000
while true do
integer i = 0
while true do
integer j = iff(i>=length(counts)?0:counts[i+1])
inv &= j
while j>=length(counts) do counts &= 0 end while
counts[j+1] += 1
ix += 1
if length(inv)=100 then
printf(1,"Inventory sequence, first 100 elements:\n%s\n",
{join_by(inv,1,20,"",fmt:="%3d")})
end if
if j=0 then exit end if
if j>=thousands then
printf(1,"First element >= %,6d is %,6d at index %,7d\n", {thousands, j, ix})
if j>=limit then return inv[1..limit] end if
thousands += 1000
end if
i += 1
end while
end while
end function
constant lim = 1e4
sequence x = tagset(lim),
y = inventory(lim)

include pGUI.e
include IupGraph.e
function get_data(Ihandle graph)
integer {w,h} = IupGetIntInt(graph,"SIZE")
IupSetInt(graph,"XTICK",iff(w<500?iff(w<350?iff(w<250?5000:2500):2000):1000))
IupSetInt(graph,"YTICK",iff(h<350?iff(h<200?iff(h<150? 200: 100):  80):  40))
return {{x,y,CD_BLUE}}
end function

IupOpen()
Ihandle graph = IupGraph(get_data,"XMIN=0,XMAX=10000,YMIN=0,YMAX=400"),
dlg = IupDialog(graph,`TITLE=gGraph,SIZE=320x240,MINSIZE=240x140`)
IupShow(dlg)
if platform()!=JS then
IupMainLoop()
end if
```
Output:
```Inventory sequence, first 100 elements:
0  1  1  0  2  2  2  0  3  2  4  1  1  0  4  4  4  1  4  0
5  5  4  1  6  2  1  0  6  7  5  1  6  3  3  1  0  7  9  5
3  6  4  4  2  0  8  9  6  4  9  4  5  2  1  3  0  9 10  7
5 10  6  6  3  1  4  2  0 10 11  8  6 11  6  9  3  2  5  3
2  0 11 11 10  8 11  7  9  4  3  6  4  5  0 12 11 10  9 13

First element >=  1,000 is  1,001 at index  24,255
First element >=  2,000 is  2,009 at index  43,301
First element >=  3,000 is  3,001 at index  61,708
First element >=  4,000 is  4,003 at index  81,456
First element >=  5,000 is  5,021 at index  98,704
First element >=  6,000 is  6,009 at index 121,342
First element >=  7,000 is  7,035 at index 151,756
First element >=  8,000 is  8,036 at index 168,804
First element >=  9,000 is  9,014 at index 184,428
First element >= 10,000 is 10,007 at index 201,788
```

## Python

```''' rosettacode.org/wiki/Inventory_sequence '''
from collections import Counter
from matplotlib.pyplot import plot

def inventory_sequence(terms):
''' From the code by Branicky at oeis.org/A342585 '''
num, alst, inventory = 0, , Counter()
for n in range(2, terms+1):
c = inventory[num]
num = 0 if c == 0 else num + 1
alst.append(c)
inventory.update([c])
return alst

biglist = inventory_sequence(201_790)
thresholds = [1000 * j for j in range(1, 11)]

for i, k in enumerate(biglist):
if i < 100:
print(f'{k:<4}', end='\n' if (i + 1) % 20 == 0 else '')
elif k >= thresholds:
print(f'\nFirst element >= {thresholds.pop(0):5}: {k:5} in position {i:6}')
if len(thresholds) == 0:
break

plot(biglist[:10_000], linewidth=0.3)
```
Output:
```0   1   1   0   2   2   2   0   3   2   4   1   1   0   4   4   4   1   4   0
5   5   4   1   6   2   1   0   6   7   5   1   6   3   3   1   0   7   9   5
3   6   4   4   2   0   8   9   6   4   9   4   5   2   1   3   0   9   10  7
5   10  6   6   3   1   4   2   0   10  11  8   6   11  6   9   3   2   5   3
2   0   11  11  10  8   11  7   9   4   3   6   4   5   0   12  11  10  9   13

First element >=  1000:  1001 in position  24255

First element >=  2000:  2009 in position  43301

First element >=  3000:  3001 in position  61708

First element >=  4000:  4003 in position  81456

First element >=  5000:  5021 in position  98704

First element >=  6000:  6009 in position 121342

First element >=  7000:  7035 in position 151756

First element >=  8000:  8036 in position 168804

First element >=  9000:  9014 in position 184428

First element >= 10000: 10007 in position 201788
```

## Raku

```use Lingua::EN::Numbers;

my (\$i, %i) = 0;

my @inventory = (^∞).map: {
my \$count = %i{\$i} // 0;
\$i = \$count ?? \$i+1 !! 0;
++%i{\$count};
\$count
}

say "Inventory sequence, first 100 elements:\n" ~
@inventory[^100].batch(20)».fmt("%2d").join: "\n";

say '';

for (1..10).map: * × 1000 {
my \$k = @inventory.first: * >= \$_, :k;
printf "First element >= %6s is %6s in position: %s\n",
.&comma, @inventory[\$k].&comma, comma \$k;
}

use SVG;
use SVG::Plot;

my @x = ^10000;

'Inventory-raku.svg'.IO.spurt:
SVG.serialize: SVG::Plot.new(
background  => 'white',
width       => 1000,
height      => 600,
plot-width  => 950,
plot-height => 550,
x           => @x,
values      => [@inventory[@x],],
title       => "Inventory Sequence - First {+@x} values (zero indexed)",
).plot: :lines;
```
Output:
```Inventory sequence, first 100 elements:
0  1  1  0  2  2  2  0  3  2  4  1  1  0  4  4  4  1  4  0
5  5  4  1  6  2  1  0  6  7  5  1  6  3  3  1  0  7  9  5
3  6  4  4  2  0  8  9  6  4  9  4  5  2  1  3  0  9 10  7
5 10  6  6  3  1  4  2  0 10 11  8  6 11  6  9  3  2  5  3
2  0 11 11 10  8 11  7  9  4  3  6  4  5  0 12 11 10  9 13

First element >=  1,000 is  1,001 in position: 24,255
First element >=  2,000 is  2,009 in position: 43,301
First element >=  3,000 is  3,001 in position: 61,708
First element >=  4,000 is  4,003 in position: 81,456
First element >=  5,000 is  5,021 in position: 98,704
First element >=  6,000 is  6,009 in position: 121,342
First element >=  7,000 is  7,035 in position: 151,756
First element >=  8,000 is  8,036 in position: 168,804
First element >=  9,000 is  9,014 in position: 184,428
First element >= 10,000 is 10,007 in position: 201,788```

converted to a .png to reduce size for display here:

## Wren

Library: DOME
Library: Wren-plot
Library: Wren-iterate
Library: Wren-fmt
```import "dome" for Window
import "graphics" for Canvas, Color
import "./plot" for Axes
import "./iterate" for Stepped
import "./fmt" for Fmt

var max = 10000
var inv = 
var counts = List.filled(max + 100, 0) // say
counts = 1
var lower = 100
var upper = 1000
var done = false
var ix = 0
while (!done) {
var i = 0
while(true) {
var j = counts[i]
counts[j] = counts[j] + 1
ix = ix + 1
if (inv.count >= lower) {
System.print("Inventory sequence, first 100 elements:")
Fmt.tprint("\$2d", inv[0..99], 20)
System.print()
lower = max + 1
}
if (j == 0) break
if (j >= upper) {
Fmt.print("First element >= \$,6d is \$,6d at index \$,7d", upper, j, ix)
if (j >= max) {
done = true
break
}
upper = upper + 1000
}
i = i + 1
}
}

// generate points for the plot
var Pts = (0...max).map { |i| [i, inv[i]] }.toList

class Main {
construct new() {
Window.title = "Inventory sequence - first 10,000 elements."
Canvas.resize(1000, 600)
Window.resize(1000, 600)
Canvas.cls(Color.white)
var axes = Axes.new(100, 500, 800, 400, 0..10000, 0..450)
axes.draw(Color.black, 2)
var xMarks = Stepped.new(0..10000, 500)
var yMarks = Stepped.new(0..400, 50)
axes.mark(xMarks, yMarks, Color.black, 2)
var xMarks2 = Stepped.new(0..10000, 1000)
var yMarks2 = Stepped.new(0..400, 100)
axes.label(xMarks2, yMarks2, Color.black, 2, Color.black)
axes.lineGraph(Pts, Color.blue, 2)
}

init() {}

update() {}

draw(alpha) {}
}

var Game = Main.new()
```
Output:

Terminal output:

```Inventory sequence, first 100 elements:
0  1  1  0  2  2  2  0  3  2  4  1  1  0  4  4  4  1  4  0
5  5  4  1  6  2  1  0  6  7  5  1  6  3  3  1  0  7  9  5
3  6  4  4  2  0  8  9  6  4  9  4  5  2  1  3  0  9 10  7
5 10  6  6  3  1  4  2  0 10 11  8  6 11  6  9  3  2  5  3
2  0 11 11 10  8 11  7  9  4  3  6  4  5  0 12 11 10  9 13

First element >=  1,000 is  1,001 at index  24,255
First element >=  2,000 is  2,009 at index  43,301
First element >=  3,000 is  3,001 at index  61,708
First element >=  4,000 is  4,003 at index  81,456
First element >=  5,000 is  5,021 at index  98,704
First element >=  6,000 is  6,009 at index 121,342
First element >=  7,000 is  7,035 at index 151,756
First element >=  8,000 is  8,036 at index 168,804
First element >=  9,000 is  9,014 at index 184,428
First element >= 10,000 is 10,007 at index 201,788
```

## XPL0

```include xpllib; \for Print

def Size = 201_790;
int Seq(Size), SeqEnd, Num, Count, N, Thresh;
[SeqEnd:= 0;
loop    [Num:= 0;
repeat  Count:= 0;
for N:= 0 to SeqEnd-1 do
if Num = Seq(N) then Count:= Count+1;
Seq(SeqEnd):= Count;
SeqEnd:= SeqEnd+1;
if SeqEnd >= Size then quit;
Num:= Num+1;
until   Count = 0;
];
Thresh:= 1000;
for N:= 0 to SeqEnd-1 do
if N < 100 then
[Print("%3.0f", float(Seq(N)));
if rem(N/20) = 19 then CrLf(0);
]
else if Seq(N) >= Thresh then
[Print("First element >= %5.0f: %5.0f in position %6.0f\n",
float(Thresh), float(Seq(N)), float(N));
if Thresh >= 10000 then return;
Thresh:= Thresh + 1000;
];
]```
Output:
```  0  1  1  0  2  2  2  0  3  2  4  1  1  0  4  4  4  1  4  0
5  5  4  1  6  2  1  0  6  7  5  1  6  3  3  1  0  7  9  5
3  6  4  4  2  0  8  9  6  4  9  4  5  2  1  3  0  9 10  7
5 10  6  6  3  1  4  2  0 10 11  8  6 11  6  9  3  2  5  3
2  0 11 11 10  8 11  7  9  4  3  6  4  5  0 12 11 10  9 13
First element >=  1000:  1001 in position  24255
First element >=  2000:  2009 in position  43301
First element >=  3000:  3001 in position  61708
First element >=  4000:  4003 in position  81456
First element >=  5000:  5021 in position  98704
First element >=  6000:  6009 in position 121342
First element >=  7000:  7035 in position 151756
First element >=  8000:  8036 in position 168804
First element >=  9000:  9014 in position 184428
First element >= 10000: 10007 in position 201788
```