LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 04-28-2017, 08:59 AM   #61
Turbocapitalist
LQ Guru
 
Registered: Apr 2005
Distribution: Linux Mint, Devuan, OpenBSD
Posts: 5,513
Blog Entries: 3

Rep: Reputation: 2784Reputation: 2784Reputation: 2784Reputation: 2784Reputation: 2784Reputation: 2784Reputation: 2784Reputation: 2784Reputation: 2784Reputation: 2784Reputation: 2784

Quote:
Originally Posted by linustalman View Post
And also have them sorted in ascending order?
Then the short way is to add in sort as in hydrurga's sed example. Or if you want to keep it all inside perl, there are several ways, but trickier to read:

Code:
shuf -i 1-47 -n 6 | perl -n -e '@a = map { chomp; $_ } sort{ $a <=> $b } <>; END{ print join(",", @a), qq(\n) ; } '
I'm sure the map() and sort() functions can be written more clearly, though.
 
1 members found this post helpful.
Old 04-28-2017, 09:04 AM   #62
linustalman
Senior Member
 
Registered: Mar 2010
Location: Ireland
Distribution: Debian 10 (Buster) x64
Posts: 4,504

Original Poster
Rep: Reputation: 445Reputation: 445Reputation: 445Reputation: 445Reputation: 445
Quote:
Originally Posted by Turbocapitalist View Post
Then the short way is to add in sort as in hydrurga's sed example. Or if you want to keep it all inside perl, there are several ways, but trickier to read:

Code:
shuf -i 1-47 -n 6 | perl -n -e '@a = map { chomp; $_ } sort{ $a <=> $b } <>; END{ print join(",", @a), qq(\n) ; } '
I'm sure the map() and sort() functions can be written more clearly, though.
Perfect TC.
 
Old 04-28-2017, 09:31 AM   #63
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (current), FreeBSD, Win10, It varies
Posts: 9,952

Rep: Reputation: 2148Reputation: 2148Reputation: 2148Reputation: 2148Reputation: 2148Reputation: 2148Reputation: 2148Reputation: 2148Reputation: 2148Reputation: 2148Reputation: 2148
Quote:
Originally Posted by linustalman View Post
Would it be possible to output the numbers on the same line and separated by commas?
yeah that is what that tr was for

Code:
 
shuf -i1-47 -n6 | tr "\n" ","
 
Old 04-28-2017, 10:16 AM   #64
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Mint 17.3
Posts: 1,814

Rep: Reputation: 639Reputation: 639Reputation: 639Reputation: 639Reputation: 639Reputation: 639
Quote:
Originally Posted by BW-userx View Post
Code:
shuf -i1-47 -n6 | tr "\n" ","
linustalman asked for a way to output the numbers on the same line and separated by commas.

tr was my first attempt but it tacks on a trailing comma.
paste doesn't cause that blemish.

Daniel B. Martin
 
1 members found this post helpful.
Old 04-28-2017, 10:27 AM   #65
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (current), FreeBSD, Win10, It varies
Posts: 9,952

Rep: Reputation: 2148Reputation: 2148Reputation: 2148Reputation: 2148Reputation: 2148Reputation: 2148Reputation: 2148Reputation: 2148Reputation: 2148Reputation: 2148Reputation: 2148
Quote:
Originally Posted by danielbmartin View Post
linustalman asked for a way to output the numbers on the same line and separated by commas.

tr was my first attempt but it tacks on a trailing comma.
paste doesn't cause that blemish.

Daniel B. Martin
I agree you got a way to eliminate that. Good Job but he never said he didn't want extra , plus that way too doesn't not give an "\n" at the end either, not in my term anyways. personally I'd go with yours.

( i didn't look through every single one before posting... my bag ...

Last edited by BW-userx; 04-28-2017 at 10:29 AM.
 
1 members found this post helpful.
Old 05-01-2017, 05:40 AM   #66
linustalman
Senior Member
 
Registered: Mar 2010
Location: Ireland
Distribution: Debian 10 (Buster) x64
Posts: 4,504

Original Poster
Rep: Reputation: 445Reputation: 445Reputation: 445Reputation: 445Reputation: 445
Post

Quote:
Originally Posted by Turbocapitalist View Post
Then the short way is to add in sort as in hydrurga's sed example. Or if you want to keep it all inside perl, there are several ways, but trickier to read:

Code:
shuf -i 1-47 -n 6 | perl -n -e '@a = map { chomp; $_ } sort{ $a <=> $b } <>; END{ print join(",", @a), qq(\n) ; } '
I'm sure the map() and sort() functions can be written more clearly, though.
Hi TC.

I just noticed that this only outputs 5 numbers. When I change the 6 in the line to 7 -- it then outputs 6 numbers.
 
Old 05-01-2017, 05:51 AM   #67
Turbocapitalist
LQ Guru
 
Registered: Apr 2005
Distribution: Linux Mint, Devuan, OpenBSD
Posts: 5,513
Blog Entries: 3

Rep: Reputation: 2784Reputation: 2784Reputation: 2784Reputation: 2784Reputation: 2784Reputation: 2784Reputation: 2784Reputation: 2784Reputation: 2784Reputation: 2784Reputation: 2784
Quote:
Originally Posted by linustalman View Post
Hi TC.

I just noticed that this only outputs 5 numbers. When I change the 6 in the line to 7 -- it then outputs 6 numbers.
Hmm. 1, 2, ..., many. I'll have to look into why that is eating one of the lines.

Try this variant:

Code:
shuf -i 1-47 -n 6 | perl -n -e 'chomp; push(@a, $_); END{ print join(",", sort { $a <=> $b } @a), qq(\n) ; } '
It is simpler.
 
1 members found this post helpful.
Old 05-01-2017, 08:52 AM   #68
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 16,238

Rep: Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453
if perl, do not use shuf, but:
Code:
#!/usr/bin/perl
use strict;
use warnings;

my $range = 100;
my %l = ();

for (my $i=1; $i<=47; $i++) {
  $l{$i} = int(rand($range));
}

my @shuffled_keys = sort { $l{$a} <=> $l{$b} } keys(%l);
my @shuffled_vals = map $shuffled_keys[$_], @shuffled_keys;

print join (", ", @shuffled_vals[1..6]);
print "\n";
 
1 members found this post helpful.
Old 05-01-2017, 12:18 PM   #69
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 16,238

Rep: Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453
obviously that was incorrect, but here is a better version (now it sorts the "result" too):
Code:
#!/usr/bin/perl
use strict;
use warnings;

my $range = 100;

my %l = map { $_ => int(rand($range)) } (1..47);
my @shuffled_keys = sort { $l{$a} <=> $l{$b} } keys(%l);

print join (", ", sort { $a <=> $b } @shuffled_keys[1..6]);
print "\n";
 
1 members found this post helpful.
Old 05-01-2017, 01:32 PM   #70
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 9,078
Blog Entries: 4

Rep: Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187
Quote:
Originally Posted by pan64 View Post
obviously that was incorrect, but here is a better version (now it sorts the "result" too):
Code:
my %l = map { $_ => int(rand($range)) } (1..47);
The problem with this approach is that there's no guarantee that the map array will not contain duplicate values. (In fact, it probably will.)

If you need to produce a randomly-arranged sequence of numbers with no duplicates, the best algorithm I've seen mimics "shuffling a deck of cards." A cursor walks the array from stem to stern, and a card is chosen at random from a position prior to or equal to that of the cursor. This card is then exchanged with the one at the cursor position. In a single pass, the "deck" is shuffled completely. The desired number of random values are then "drawn" from either end of the deck.

But if I only needed six values, and I was never going to need six more, to go to this amount of trouble is unnecessary. Simply generate six values. Then, comb through them looking for dupes. Replace any dupes with randomly-chosen values and "rinse and repeat" until there are no dupes. If the number of values needed (6) is very-small in relation to their range (1..42), the odds are in your favor.

Last edited by sundialsvcs; 05-01-2017 at 01:34 PM.
 
Old 05-01-2017, 01:57 PM   #71
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 16,238

Rep: Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453
Quote:
The problem with this approach is that there's no guarantee that the map array will not contain duplicate values. (In fact, it probably will.)
Yes, but that is not a problem. The value of $range is not important, and also int() is not really required. But it will make this (implementation) a bit more expressive I think.
The trick is I shuffle the indices, not the values. That map array is (values are) only used to shuffle the indices of %l (the keys), which are unique. That means I will reorder them by values, and I do not really care if the values are the same, they will be [re-]ordered/sorted anyway). This is how shuffle should work I think.
As you can see in the last line I use the variable shuffled_keys to get 6 numbers.
post #68 is simply wrong, overcomplicated and sometimes it also drops an error message too.
 
Old 05-02-2017, 01:57 PM   #72
linustalman
Senior Member
 
Registered: Mar 2010
Location: Ireland
Distribution: Debian 10 (Buster) x64
Posts: 4,504

Original Poster
Rep: Reputation: 445Reputation: 445Reputation: 445Reputation: 445Reputation: 445
Thumbs up

Quote:
Originally Posted by Turbocapitalist View Post
Hmm. 1, 2, ..., many. I'll have to look into why that is eating one of the lines.

Try this variant:

Code:
shuf -i 1-47 -n 6 | perl -n -e 'chomp; push(@a, $_); END{ print join(",", sort { $a <=> $b } @a), qq(\n) ; } '
It is simpler.
Perfect! Thanks again guys. :-)
 
Old 05-03-2017, 08:52 AM   #73
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 9,078
Blog Entries: 4

Rep: Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187Reputation: 3187
Quote:
Originally Posted by pan64 View Post
Yes, but that is not a problem. The value of $range is not important, and also int() is not really required. But it will make this (implementation) a bit more expressive I think. The trick is I shuffle the indices, not the values. [...]
A deck of cards must not contain duplicates. Whether you shuffle the indices or shuffle the numbers, the result of drawing every single card in the deck must "probably, never" produce an identical card.

If you call rand(42) 42 times, you will get duplicates: (The output shown below has been reformatted into six-digit groups.)
Code:
$ perl -e 'for my $i (1..48) { print int(rand(47)) . " "} ;'

20 31 33 26 16 14
14 0 38 24 9 21 
12 1 11 30 20 23
29 2 45 43 3 4 
24 13 18 32 1 2 
11 18 34 39 34 24   (duplicate = 34)
46 36 43 23 35 31 
4 21 29 6 12 3
31 is duplicated, also 1, 11, and so on.

Nevertheless, if you simply need six numbers, you can simply produce six and check for duplicates. In the example above, the first six numbers contain no duplicates. In fact, only one of the 6-digit groups contains a duplicate value within itself. (The probability of this is about 50%.)

Furthermore, the choice of algorithm could have subtle statistical implications, if, say, you were performing this loop repeatedly to take "random samples" from a population. If you shuffled a deck of 48 cards, and drew 6 cards from the deck 8 consecutive times, then each of the 8 samples would contain no elements in common. Which is not the same as generating 8 consecutive random groups each one of which contains no duplicates. In the list above, "31" would be sampled twice, likewise "1" and "11" and so on, although each 6-element sample is individually "random." In one case, the draws are causally related to all other draws in the same 8-draw group; in the second, they are not. So, it depends upon what you actually want to do.

Last edited by sundialsvcs; 05-03-2017 at 09:11 AM.
 
Old 05-03-2017, 10:41 AM   #74
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 16,238

Rep: Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453Reputation: 5453
you still did not catch the trick:
initially I have 47 integers (1..47) and associated 47 random number (these random numbers are irrelevant, almost anything can be used, int(rand($range)) is just one possibility - the only thing we need is to generate more or less different numbers)
Code:
%l = (1 => random, 2 => random, .... )
Then I shuffle the keys of %l by sorting based on values. That is
Code:
my @shuffled_keys = sort { $l{$a} <=> $l{$b} } keys(%l);
this will randomize the keys, and the values will be ordered (ascending). We may have equal values, I do not really care about that, but we still cannot have duplicates on keys.
And finally I need six items, that is:
Code:
@shuffled_keys[1..6]
# or
@shuffled_keys[19..25]
# or any similar
# and finally I sort and print it:
print join (", ", sort { $a <=> $b } @shuffled_keys[1..6]);
 
1 members found this post helpful.
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] sed - replacing random numbers followed with space and more random chars gluposti Linux - Newbie 7 05-07-2012 07:36 PM
Generate random numbers in C program ssaslam Linux - Newbie 5 10-23-2008 08:28 PM
Generate random numbers in C program ssaslam Linux - Newbie 1 02-21-2008 11:39 PM
using /dev/random to output random numbers on a text file guguma Programming 4 04-02-2007 01:42 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 07:31 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration