(50G) list of non repeated #,fi —> list of repeated increasing #

+- HP Forums (https://www.hpmuseum.org/forum)
+-- Forum: HP Software Libraries (https://www.hpmuseum.org/forum/forum-10.html)
+--- Forum: General Software Library (https://www.hpmuseum.org/forum/forum-13.html)
+--- Thread: (50G) list of non repeated #,fi —> list of repeated increasing # (/thread-23983.html)



(50G) list of non repeated #,fi —> list of repeated increasing # - Gil - 2025-08-30

Use/Example 
Enter the initial list of (unordered) unrepeated numbers, say
{ 50 20 30 10 40 } in stack level 2. 

Then enter the list of associated frequencies, all integers >0, say 
{ 3 4 1 2 1 } in stack level 1.

Run the program to get 
{ 10 10 20 20 20 20 30 40 50 50 50 }

Explanation
smallest element of initial list (in stack level 2) is 10, to be repeated twice (according to list in stack level 1),..., largest element of initial list (always in stack level 2) is 50, to be repeated 3 times (again according to list in stack level 1).

Code 
\<< DUP SIZE 0 \-> l lf s lo
  \<< l SORT 'lo' STO { } 1 s
    FOR i lf l lo i GET POS GET +
    NEXT 'lf' STO { } 1 s
    FOR i 1 lf i GET
      START lo i GET +
      NEXT
    NEXT
  \>>
\>>

Observations
1) Both lists should be of same dimension. 
2) Can be used to visualise quantiles when in presence of frequencies.
3) No restriction on possible elements in stack 3, 4, 5, 6...

Based on Fliszt's smart idea of tagging the elements, here is a much shorter and faster version, now included here with ending VER3, that does not use variables:

\<< \->TAG { } SWAP DUP SIZE 1 SWAP
  FOR i DUP i GET OBJ\-> OBJ\-> 1 \->LIST SWAP CON OBJ\-> OBJ\-> DROP \->LIST ROT + SWAP
  NEXT DROP SORT
\>>


RE: (50G) list of non repeated #,fi —> list of repeated increasing # - John Keith - 2025-08-30

Using ListExt this is simply

Code:
\<< 2. \->LIST LRPC\-> SORT
\>>

Faster for large lists if you also use LSORT instead of SORT.


RE: (50G) list of non repeated #,fi —> list of repeated increasing # - avsebastian - 2025-09-06

(2025-08-30, 09:08)John Keith Wrote: Using ListExt this is simply

Code:
\<< 2. \->LIST LRPC\-> SORT
\>>

Faster for large lists if you also use LSORT instead of SORT.

oh, good point


RE: (50G) list of non repeated #,fi —> list of repeated increasing # - FLISZT - 2025-09-08

Hello,


I found the exercise very interesting, so I decided to give it a try. My goal was to avoid using variables. That may explain why my program is somewhat cumbersome: it involves a lot of “acrobatics” with the stack! Not to mention that I'm just a weekend programmer…

The two lists must be entered in the order specified by Gil, otherwise the first instruction in the program (SWAP) will have to be deleted.

The initial list can contained repeated numbers. Ex.: With { 2 2 2 } { 2 2 2 }, the resultat will be { 2 2 2 2 2 2 }. Six "2".

The program will not work if the second list contains one or more zeros. Important : the stack must be empty!


\<<
  SWAP  \->TAG  OBJ\->  1  SWAP
  FOR  i
         i  ROLL  \->STR  ":"  ""  SREPL  DROP
  NEXT
  DEPTH  2  *  1  SWAP
  FOR  i
         i  ROLL  STR\->
  2  STEP
  DEPTH  DUP  SWAP  2  /  1  +
  FOR  i
         i  ROLL  i  ROLL
         {}  1  ROT  START  OVER  +  NEXT  NIP
  −1  STEP
  DEPTH  2  SWAP
  START
         +
  NEXT
  SORT
\>>


RE: (50G) list of non repeated #,fi —> list of repeated increasing # - Gil - 2025-09-08

I tried your program 
with 

{ 10. 9. 5. 2. 15. } { 3. 3. 3. 4. 5. }
and got { 2. 3. 3. 4. 5. 5. 9. 10. 10. 10. 15. }

My program looks for the smallest number of the first list : 2 ; then it looks how many of this element is to be taken: 4. Then the new list should start with four 2.

Then my program looks for the next smallest element in the first list : 5. The second list says that that number 5 is to be taken three times. Etc. 

The final list is then { 2. 2. 2. 2. 5. 5. 5. 9. 9. 9. 10. 10. 10. 15. 15. 15. 15. 15. }.


RE: (50G) list of non repeated #,fi —> list of repeated increasing # - FLISZT - 2025-09-08

I just tested my program with your test set:

2:         { 10  9  5  2  15 }
1:             { 3  3  3  4  5 }

I've got the expected result:  { 2  2  2  2  5  5  5  9  9  9  10  10  10  15  15  15  15  15 }

I then checked for typos, but I couldn't find any.

BYTES returns:  # 111011b / 181.


RE: (50G) list of non repeated #,fi —> list of repeated increasing # - Gil - 2025-09-08

Yes, your program is correct. My apologies. 

I copied it into my phone with EMU48. 

Then I got a string to be converted with the program INOUT. 

But the copied string on the EMU48/Phone appears with a black square before the instruction 1 STEP,
instead of the minus sign (-) before the instruction 1 STEP ! 

With the INOUT program, then the final result is just 1 STEP instead of your correct -1 STEP.

But the correct output with BYTES should be 
# 1010101000111011b
and 181.


RE: (50G) list of non repeated #,fi —> list of repeated increasing # - FLISZT - 2025-09-08

(2025-09-08, 19:07)Gil Wrote: Yes, your program is correct. My apologies. 

I copied it into my phone with EMU48. 

Then I got a string to be converted with the program INOUT. 

But the copied string on the EMU48/Phone appears with a black square before the instruction 1 STEP,
instead of the minus sign (-) before the instruction 1 STEP ! 

With the INOUT program, then the final result is just 1 STEP instead of your correct -1 STEP.

But the correct output with BYTES should be 
# 1010101000111011b
and 181.

Oh yes, I'm sorry, that's my fault.
I usually use − instead of - for the minus sign. The INOUT program doesn't seem to understand that.

And you're right about the output with BYTES.
The binary word length had remained at its previous setting (6 STWS).
With a length of 64 bits, I obtain the value you gave, or # AA3Bh.


RE: (50G) list of non repeated #,fi —> list of repeated increasing # - Gil - 2025-09-09

Fliszt, 

Quite an original and smart approach!

Instead of DUP SWAP, you could have here just DUP.

Regards, 
Gil


RE: (50G) list of non repeated #,fi —> list of repeated increasing # - Gil - 2025-09-09

Looking at your program, I realised that it was much simpler to sort the final list (with all the repeated elements) at the end of the program.

Here is here my much shorter version:

\<< \-> l f
  \<< { } l SIZE 1 SWAP
    FOR i f i GET 1 SWAP
      START l i GET +
      NEXT
    NEXT SORT
  \>>
\>>


RE: (50G) list of non repeated #,fi —> list of repeated increasing # - Gil - 2025-09-09

Based on your smart idea of tagging the elements, here is a much shorter and faster version than yours, equally without using variables:

\<< \->TAG { } SWAP DUP SIZE 1 SWAP
  FOR i DUP i GET OBJ\-> OBJ\-> 1 \->LIST SWAP CON OBJ\-> OBJ\-> DROP \->LIST ROT + SWAP
  NEXT DROP SORT
\>>

Moreover, it does not depend on the possible elements lying previously on the stack before the two lists.


RE: (50G) list of non repeated #,fi —> list of repeated increasing # - DavidM - 2025-09-09

Given that the original target platform for this thread was the 50g, two built-in commands come to mind here that can simplify the approach: NDUPN and DOLIST.

NDUPN makes N copies of the identified object, then leaves that count on the stack for further processing.  In this case, we don't need to do anything else with the count, so it is simply dropped.

DOLIST comes to mind any time there are multiple lists involved, especially if there is a relationship between the list elements that aligns with the elements' positions in their list.  We definitely have that situation here.

Here's my suggestion for a real (or emulated) 50g:
Code:
@ Size: 41.0 bytes, CRC: 0922h

\<<
  2 \<< NDUPN DROP \>> DOLIST
  SORT
\>>

This is a fairly efficient approach to the given problem, but the performance of SORT slows down considerably as the input lists grow. Let's use 100-element lists for the input to see what happens with the performance on a real 50g:
Code:
{ 310 390 50 20 670 840 460 730 350 950 620 220 740 140 10 700 190 680 590 690 830 800 920 500 960 100 40 30 300 110 520 160 750 820 340 90 250 240 640 210 770 600 510 610 850 270 560 860 180 720 940 370 790 970 540 650 120 440 410 230 430 170 320 580 150 630 290 480 980 930 990 470 260 400 710 550 570 280 880 900 130 810 60 450 330 1000 360 200 490 910 420 870 780 760 890 660 70 530 80 380 }

{ 2 4 1 2 1 4 1 4 1 4 3 2 4 4 2 4 1 3 4 4 3 4 3 4 3 3 3 1 1 3 1 4 4 4 4 3 1 2 3 4 3 3 4 1 2 4 1 3 2 1 1 2 3 4 2 4 3 2 1 2 3 1 2 2 2 4 3 3 3 3 3 2 4 1 4 3 1 1 1 1 2 3 1 4 4 4 4 1 2 2 3 3 3 3 1 2 1 3 1 4 }

Using the 100-element lists as input for the above program takes a little over 11 seconds on a real 50g.  If SORT is replaced by LSORT, the total time taken drops to about 0.7 seconds.  Thanks Werner!


RE: (50G) list of non repeated #,fi —> list of repeated increasing # - Gil - 2025-09-09

David's most compact solution: just magical!


RE: (50G) list of non repeated #,fi —> list of repeated increasing # - FLISZT - 2025-09-09

Yes Gil, I had no doubt that my program could be improved. You did it, and you did it well.
What was important to me was to succeed in creating a functional program and winning my battle with (against) the stack.

Your suggestion to replace DUP SWAP with just DUP is more than accurate. I probably had to make a change and forget about SWAP, especially since it's “invisible” in the sense that it doesn't cause any errors.


Well done, David! But tell me why I didn't think of that when I know DOLIST. LOL!
Maybe because of my battle with the stack. Anyway, no regrets. My approach was instructive… and original (and smart). Gil said so.  Smile


Regards


RE: (50G) list of non repeated #,fi —> list of repeated increasing # - John Keith - 2025-09-09

Going back to ListExt, we can avoid sorting the large final list by using KSORT . 

Code:
\<< SWAP
  \<< LSORT
  \>> KSORT SWAP 2. \->LIST LRPC\->
\>>

Using David's 100-element lists above, 0.59 seconds on a physical 50g.

Of course, David's elegant program is 11 bytes shorter and requires no external commands. Smile


RE: (50G) list of non repeated #,fi —> list of repeated increasing # - Gil - 2025-09-10

Just mixing up the idea of Fliszt (tagging the objects) and, now, the suggestion of David (NDUPN instead of command CON), the version 3 of my programs becomes:

\<< \->TAG { } SWAP DUP SIZE 1 SWAP
  FOR i DUP i GET OBJ\-> OBJ\-> NDUPN \->LIST ROT + SWAP
  NEXT DROP SORT
\>>