37
\$\begingroup\$

Create a program that prints all whole numbers inclusively between an interval (a, b), and replaces multiples of 8 in the sequence with random (uniformly distributed, independent of other characters), non-numeric, non-whitespace, printable ASCII characters.

Assume 0 < a < b in all cases.

If the number has more than 1 digit, make sure the amount of characters in the replacement matches!

Examples:

(1, 16) -> 1 2 3 4 5 6 7 $ 9 10 11 12 13 14 15 n@

(115, 123) -> 115, 116, 117, 118, 119, :F<, 121, 122, 123

(1, 3) -> 1 2 3

Non-Examples:

(1, 16) -> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

(115, 123) -> 115 116 117 118 119 $ 121 122 123

This is code golf, so the shortest code in bytes wins!

Current Winner:

Pyke (21 bytes) by muddyfish

Most Popular:

Python 2 (119 bytes) by Dennis

\$\endgroup\$
10
  • 13
    \$\begingroup\$ Congrats on making a challenge that combines all the super long things to implement in my golfing language \$\endgroup\$
    – Blue
    Commented Dec 24, 2016 at 0:16
  • 1
    \$\begingroup\$ @muddyfish i mean it is a challenge ;) \$\endgroup\$ Commented Dec 24, 2016 at 0:16
  • \$\begingroup\$ I'm not sure if I am missing something, but should the random characters be unique or not? For example if the input was 16, 16 then could the output be aa? If this is not the case, what about if the number has more than 85 digits (assuming I counted correctly)? \$\endgroup\$ Commented Dec 24, 2016 at 4:09
  • \$\begingroup\$ @FryAmTheEggman each character should be unique mostly but if "a" and "a" are randomly selected consecutively that is ok, but it shouldnt happen in all cases because the probability is so low \$\endgroup\$ Commented Dec 24, 2016 at 4:14
  • \$\begingroup\$ @FryAmTheEggman and the case 16, 16 in the other examples either returns 0 or 2 random characters but dont worry about that case as a will always strictly be less than b \$\endgroup\$ Commented Dec 24, 2016 at 4:15

31 Answers 31

10
\$\begingroup\$

Python 2, 119 bytes

import random,string
def f(a,b):print`[random.choice(string.printable[10:95])for _ in`a`]`[2+a%8*b::5]or a;a<b<f(a+1,b)

Try it online!

\$\endgroup\$
1
  • 5
    \$\begingroup\$ To quote Flp.Tkc: "One does not simply outgolf Dennis" \$\endgroup\$ Commented Dec 24, 2016 at 19:07
10
\$\begingroup\$

Python 2, 126 bytes

Try it online!

import random,string
def f(a,b):
 while b/a:print[a,eval('random.choice(string.printable[10:-6])+'*len(`a`)+"''")][a%8<1];a+=1

Many thanks to Flp.Tkc and EasterlyIrk for all of their help!

\$\endgroup\$
2
  • 2
    \$\begingroup\$ You can use b/a instead of a<=b and you don't need the ; at the end. Also import random,string saves a few bytes. tio.run/nexus/… \$\endgroup\$
    – Dennis
    Commented Dec 24, 2016 at 16:16
  • \$\begingroup\$ @Dennis, thank you, that took off 7 bytes! \$\endgroup\$
    – auden
    Commented Dec 24, 2016 at 16:59
6
\$\begingroup\$

zsh, 100 98 bytes

for i in {$1..$2};{((i%8))&&<<<$i||<<<`yes 'shuf -e {!..~}|grep "[^0-9]"|head -c1'|head -$#i|zsh`}

The two input arguments are passed as command line arguments, and the numbers are output on separate lines.

for i in {$1..$2};{   # loop through the range
((i%8))&&             # if the number is not divisible by 8 (i % 8 != 0),
<<<$i||               # output it
<<<`                  # otherwise, output the following:
yes '                 # using `yes' as a golfy loop
shuf -e {\!..\~}      # shuffle the range of printable ASCII (minus space)
|grep "[^0-9]"        # get rid of numbers
|head -c1'            # take the first character
|head -$#i            # obtain a string with that code repeated len(i) times... 
|zsh                  # ... and eval it
`}
\$\endgroup\$
2
  • \$\begingroup\$ May I ask why you are outputting the numbers that are divisible by 8? \$\endgroup\$ Commented Dec 24, 2016 at 0:56
  • 1
    \$\begingroup\$ @Caleb Whoops, that was a typo. It was meant to read "not divisible by 8." \$\endgroup\$
    – Doorknob
    Commented Dec 24, 2016 at 1:03
5
\$\begingroup\$

Pyke, 22 21 bytes

h1:Fi8%!I`lV~Kl7T>Hs0

Try it here!

Takes input in the form: higher, lower

h1:                   -  range(lower, higher+1, 1)
   F                  - for i in ^:
    i8%               -    i % 8 
       !              -   not ^
        I             -  if ^:
         `l           -    len(str(i))
           V          -   repeat V ^ times
            ~K        -        printable_ascii
              l7      -       ^.strip()
                T>    -      ^[10:]
                  H   -     random.choice(^)
                   s0 -    sum(^)
\$\endgroup\$
3
  • \$\begingroup\$ Lists are all good! \$\endgroup\$ Commented Dec 24, 2016 at 16:53
  • \$\begingroup\$ This is interesting, the first case ive seen where 8n, 8n causes an error \$\endgroup\$ Commented Dec 24, 2016 at 16:57
  • \$\begingroup\$ my bad I misread the output \$\endgroup\$ Commented Dec 24, 2016 at 16:59
5
\$\begingroup\$

Mathematica, 96 bytes

Range@##/.a_?(8∣#&):>Join[33~(c=CharacterRange)~47,58~c~127]~RandomChoice~⌊Log10@a+1⌋<>""&

Explanation

For inputs m and n:

Range@##

Generate {m, m + 1, m + 2, ... , n}

/.a_?(8∣#&):>

For all numbers that are divisible by 8 (call that a), apply this replacement rule:

Join[33~(c=CharacterRange)~47,58~c~127]

Get a list of all printable ASCII characters, except digits.

... ~RandomChoice~⌊Log10@a+1⌋

Pseudo-randomly choose Floor[Log10[a] + 1] characters from the list, allowing duplicates.

<>""

Join the characters.

\$\endgroup\$
1
  • \$\begingroup\$ another approach for 96 bytes using FromCharacterCode (r=Range)@##/.a_?(8∣#&):>FromCharacterCode[Join[33~r~47,58~r~127]~RandomChoice~⌊Log10@a+1⌋]<>""& \$\endgroup\$
    – buttercrab
    Commented Feb 6, 2019 at 14:13
5
\$\begingroup\$

R, 73 bytes

i=scan();x=i[1]:i[2];x[!x%%8]=sample(sapply(c(32:46,58:126),intToUtf8));x

Reads input from stdin and replaces replaces numbers divisible by 8 with a uniformly chosen sample of ascii characters in the range 32...47, 58...126. To draw the random sample we need a vector of characters, unfortunately intToUtf8() returns one string rather than a vector so we also have to vectorize it over the range using sapply.

\$\endgroup\$
5
\$\begingroup\$

Python 2, 126 bytes

(one does not simply outgolf Dennis)

Seeing as I did a lot of work on heather's answer, I thought I'd post my own solutions too.

import random,string
def f(a,b):
 while b/a:print[a,eval('random.choice(string.printable[10:-6])+'*len(`a`)+"''")][a%8<1];a+=1

This is a function which takes two arguments and prints directly to STDOUT.

127 bytes

import random,string
lambda a,b:[[x,eval('random.choice(string.printable[10:-6])+'*len(`x`)+`''`)][x%8<1]for x in range(a,b+1)]

This is an unnamed anonymous function - to use, assign to a variable (such as f), and then call with f(a, b). This returns the output as a list.

\$\endgroup\$
3
  • \$\begingroup\$ This is incorrect. The randomly selected characters may not contain digits. \$\endgroup\$
    – Dennis
    Commented Dec 24, 2016 at 16:20
  • \$\begingroup\$ @Dennis alright, back to my splicing idea :P Thanks for the heads up \$\endgroup\$
    – FlipTack
    Commented Dec 24, 2016 at 16:23
  • \$\begingroup\$ Python 2 seems to be popular contender, i love it! \$\endgroup\$ Commented Dec 24, 2016 at 16:50
4
\$\begingroup\$

Pip, 28 bytes

Fia,b+1Pi%8?i{RC@>PA@`\D`}Mi

Takes the numbers as command-line arguments and prints a newline-separated list of results. Try it online!

Explanation:

                              a,b are cmdline args; PA is string of all printable ASCII
Fia,b+1                       For i in range(a, b+1):
       P                       Print this:
        i%8?i                  If i%8 is truthy (nonzero), i; otherwise:
             {           }Mi   Map this function to the digits of i:
                @>PA           All but the first character of PA (removes space)
                    @`\D`      Find all regex matches of \D (nondigits)
              RC               Random choice from that list of characters
                               The map operation returns a list, which is concatenated
                               before printing
\$\endgroup\$
4
\$\begingroup\$

JavaScript (ES6), 114 bytes

f=(x,y)=>(x+"").replace(/./g,d=>x%8?d:String.fromCharCode((q=Math.random()*84)+(q>15?43:33)))+(x<y?[,f(x+1,y)]:"")

O.textContent = f(1,200)
<pre id=O>

Those darn built-ins with 23-byte names....

\$\endgroup\$
2
  • 1
    \$\begingroup\$ The replacement chars should be non-numerical \$\endgroup\$
    – LarsW
    Commented Dec 24, 2016 at 22:08
  • \$\begingroup\$ @LarsW Somehow missed that, thanks \$\endgroup\$ Commented Dec 25, 2016 at 1:50
4
\$\begingroup\$

Bash + apg, 64, 76, 73 bytes

EDITS:

  • Fixed the "8 8" issue, exclude numeric characters from a set of random chars, +12 bytes

  • -3 bytes, replaced $1 $2 with $@, thx @pxeger

Golfed

seq $@|sed "$[(7&(8-$1%8))+1]~8s/.*/a=&;apg -a1 -n1 -Mcsl -m\${#a} -x0/e"

Test

>./crazy8 8 8
$

>./crazy8 115 123
115
116
117
118
119
As_
121
122
123

>./crazy8 1 16
1
2
3
4
5
6
7
"
9
10
11
12
13
14
15
x!
\$\endgroup\$
4
  • \$\begingroup\$ Could you give is a brief walk through? Also im curious to see what crazy8 8 8 would yield \$\endgroup\$ Commented Dec 24, 2016 at 16:06
  • \$\begingroup\$ @Caleb, actually it will just output a as is, for 8 8, looks like I've over-golfed it a bit, working on a fix now. It also does not filter out digits from the random string character set (I've missed that too). \$\endgroup\$
    – zeppelin
    Commented Dec 24, 2016 at 20:08
  • \$\begingroup\$ can't you replace $1 $2 with $@? \$\endgroup\$
    – pxeger
    Commented Mar 13, 2021 at 21:07
  • \$\begingroup\$ @pxeger True, thank you ! \$\endgroup\$
    – zeppelin
    Commented Mar 14, 2021 at 18:22
3
\$\begingroup\$

MATL, 26 bytes

&:"@8\?@}6Y24Y2X-Xz@VnT&Zr

Try it online!

Explanation

&:        % Input a and b (implicit). Push range [a a+1 ... b]
"         % For each k in that range
  @       %   Push k
  8\      %   Modulo 8
  ?       %   If non-zero
    @     %     Push k
  }       %   Else
    6Y2   %     Push string of all printable ASCII chars
    4Y2   %     Push string '0123456789'
    X-    %     Set difference
    Xz    %     Remove space. Gives string of possible random chars
    @Vn   %     Push number of digits of k
    T&Zr  %     Random sample with replacement of that many chars from the string
          % End if, end for each, display (implicit)
\$\endgroup\$
2
  • \$\begingroup\$ Wow, cool! Nice answer. +1 \$\endgroup\$
    – auden
    Commented Dec 24, 2016 at 0:54
  • \$\begingroup\$ @heather Thanks! I have a feeling it could be made shorter... \$\endgroup\$
    – Luis Mendo
    Commented Dec 24, 2016 at 0:55
3
\$\begingroup\$

Pyth, 24 bytes

jm?%d8dsmO-r\~\ jkUT`d}F

Try it online!

Explanation:

jm?%d8dsmO-r\~\ jkUT`d}FQ  # Auto-fill variables
                      }FQ  # Splat inclusive range on the input
 m?%d8d                    # Map over each number, if it isn't divisible by 8 return it
       smO          `d     # for each other number, select a character at random for
                             each of it's digits and then flatten into one string
           r\~\            # Printable ASCII excluding space
          -     jkUT       # Setwise difference with numeric values (remove numbers)
j                          # Join with newlines
\$\endgroup\$
2
\$\begingroup\$

Perl 6, 60 bytes

{map {$_%8??$_!!S:g/./{grep(/\D/,"!".."~").pick}/},$^a..$^b}

Explanation:

  • { map { }, $^a .. $^b }: A lambda that takes two arguments, generates the list of integers in that range, and returns it with the following transformation applied to each element:
  • $_ % 8 ?? $_ !!: If the element is not divisible by 8, pass it on unchanged. Otherwise...
  • S:g/./{ }/: ...replace each character of its string representation with the value generated by this expression:
  • grep(/\D/, "!" .. "~").pick: Generate the range of characters between ! and ~ (in Unicode order), filter out digits, and randomly pick one of the remaining characters.
\$\endgroup\$
0
2
\$\begingroup\$

Perl, 66 bytes

map{$_%8||s%.%do{$_=chr rand 126}until/[!-\/:-~]/;$_%ge;say}<>..<>

Run with -E flag:

perl -E 'map{$_%8||s%.%do{$_=chr rand 126}until/[!-\/:-~]/;$_%ge;say}<>..<>' <<< "8
16"

This is pretty straight forward:
-<>..<> creates a list of the numbers between the 2 inputs number. And then map iterates over it:
-$_%8||... : the ... are executed only if $_ is a multiple of 8.
-s%.%xxx%ge : replace every character with xxx.
- do{$_=chr rand 126}until/[!-\/:-~]/ pick a random character (from codes 0 to 126) until we get one that satisfies /[!-\/:-~]/, ie. one that is printable and is not a digit.
- say: print it.

\$\endgroup\$
2
\$\begingroup\$

C (gcc), 129 119 bytes

s(a,r){a&&s(!isdigit(r=rand()%94+33)?putchar(r),a/10:a,0);}f(a,b){b>a&&f(a,b-1);b%8?printf("%d",b):s(b,0);printf(" ");}

Try it online!

129 → 119 Use the %94+33 trick from O.O.Balance

Ungolfed:

s(a,r){
    a&&                                  // Loop recursively on a!=0
    s(!isdigit(r=rand()%94+33)           // Test random selection
      ?putchar(r),a/10                   // Print and reduce a
      :a                                 // Retry random selection
      ,0);                               // Second arg, recurse
}
f(a,b){
    b>a&&                                // Loop recursively on b>a
    f(a,b-1);                            // Reduce b, recurse
    b%8?printf("%d",b)                   // Print non 8's
       :s(b,0);                          // Call s() for 8's
    printf(" ");                         // Space separator
}
\$\endgroup\$
3
  • \$\begingroup\$ You can save 3 bytes if you change to a newline separator (puts instead of printf). \$\endgroup\$ Commented Apr 13, 2018 at 9:12
  • \$\begingroup\$ It's more fun to play with your solution :-) \$\endgroup\$
    – jxh
    Commented Apr 13, 2018 at 18:51
  • \$\begingroup\$ 115 bytes \$\endgroup\$
    – ceilingcat
    Commented Jan 23, 2021 at 19:23
2
\$\begingroup\$

C, 157 115 bytes

f(a,b){b-a&&f(a,b-1);if(b%8)printf("%d",b);else for(;b;b/=10){while(isdigit(a=rand()%94+33));putchar(a);}puts("");}

Try it online here. Thanks to jxh for golfing 42 bytes.

Ungolfed version:

f(a, b) { // recursive function, parameters are implicitly int
    b-a && f(a, b-1); // recurse until a = b
    if(b % 8)            // if the number is a multiple of 8
        printf("%d", b); // simply print it
    else for(; b; b /= 10) { // while b > 0, lop off the last digit
        while(isdigit(a = rand() % 94 + 33)); // generate random characters in ASCII range [33, 127] until one is non-numeric
        putchar(a); // print the character
    }
    puts(""); // print a newline
}
\$\endgroup\$
2
2
\$\begingroup\$

Java 10, 149 147 bytes (lambda function)

b->a->{var r="";for(;a<=b;r+=" ",a++)for(var c:(a+"").split("")){char t=0;for(;t<33|t>126|t>47&t<59;t*=Math.random())t=127;r+=a%8<1?t:c;}return r;}

Try it online.

Java 10, 227 225 bytes (full program)

interface M{static void main(String[]A){var r="";for(var a=new Long(A[0]);a<=new Long(A[1]);r+=" ",a++)for(var c:(a+"").split("")){char t=0;for(;t<33|t>126|t>47&t<59;t*=Math.random())t=127;r+=a%8<1?t:c;}System.out.print(r);}}

Try it online.

Explanation:

b->a->{          // Method with two integer parameters and String return-type
  var r="";      //  Result-String, starting empty
  for(;a<=b      //  Loop as long as `a` is smaller than or equal to `b`
      ;          //    After every iteration:
       r+=" ",   //     Append a space to the result-String
       a++)      //     And increase `a` by 1
    for(var c:(a+"").split("")){
                 //   Inner loop over the characters of the current number
      char t=0;  //    Random-char, starting at 0
      for(;t<33|t>126|t>47&t<59;
                 //    Loop until `t` is a non-digit printable ASCII char
          t*=Math.random())t=127;
                 //     Set `t` to a random character with a unicode in the range [0,127)
      r+=a%8<1?  //   If the current `a` is divisible by 8:
          t      //    Append the random character
         :       //   Else:
          c;}    //    Append the digit instead
  return r;}     //  Return the result
\$\endgroup\$
3
  • \$\begingroup\$ range [0,127] does not conform to spec: "non-numeric, non-whitespace, printable ASCII" \$\endgroup\$ Commented Apr 4, 2018 at 14:59
  • \$\begingroup\$ @O.O.Balance Maybe my comment isn't very well explained, but that's where the t<33|(t>47&t<59)|t>126; is for above it. It basically generated a random number in the range [0,127), then checks if it's valid (so in the range [33..47,59..126], all printable non-digit ASCII characters). If it is: good, append it. If not: generate a random number in the range [0,127) again and validate it again until we've found a valid character. \$\endgroup\$ Commented Apr 4, 2018 at 15:27
  • \$\begingroup\$ No, I think your comment is fine. My bad :) \$\endgroup\$ Commented Apr 4, 2018 at 15:46
2
+100
\$\begingroup\$

APL (Dyalog Extended), 32 bytes

{(?84¨⍕⍵)⊇⎕D~⍨'!'…'~'}¨@{0=8|⍵}…

Try it online!

Huge thanks to Adám and dzaima for their help. First time using Dyalog Extended!

Explanation:

{(?84¨⍕⍵)⊇⎕D~⍨'!'…'~'}¨@{0=8|⍵}…  ⍝ Dyadic 2-train

                               …  ⍝ Tacit range: list of numbers from left arg 
                                  ⍝ to right arg inclusive
{(?84¨⍕⍵)⊇⎕D~⍨'!'…'~'}¨@{0=8|⍵}   ⍝ Monadic function applied to above          
                        {     }   ⍝ Function definition
                           8|⍵    ⍝ 8 modulo every item in our range
                         0=       ⍝ Transform list into a boolean vector, with
                                  ⍝ 1 where item was equal to zero, 0 otherwise
                      ¨@          ⍝ Applies left function to each item selected
                                  ⍝ by above
{                    }            ⍝ Function definition
              '!'…'~'             ⍝ Range of all printable ASCII chars
          ⎕D~⍨                    ⍝ Remove numeric characters from above
 (    ⍕⍵)                         ⍝ Convert function argument to string
                                  ⍝ (e.g., 123 -> "123")
   84¨                            ⍝ For each character, replace with number 84
                                  ⍝ (number of non-numeric printable ASCII chars)
  ?                               ⍝ Generate random number from 1-84 for each
                                  ⍝ 84 in list
         ⊇                        ⍝ Index the ASCII char list with above random
                                  ⍝ numbers
\$\endgroup\$
2
\$\begingroup\$

Inlined version

Scala, 132 bytes

def S(a:Int,b:Int)= a to b map(x=>if(x%8==0)Random.nextInt(((33 to 47)++(58 to 126)).length).toChar.toString else String.valueOf(x))

Try it online!

Scala, 198 bytes

An improved functional version with immutable state (03-04-2018)

  def S(a: Int, b: Int)={
    val c=(33 to 47)++(58 to 126)
    val r = (a to b).toStream.map {case x if x%8==0=>c(Random.nextInt(c.length)).toChar.toString
      case x => String.valueOf(x)}
    r}

Try it online!

A functional style solution in Scala (350 bytes) for the fun of it.

def r(a:Int, b:Int)={
    var l=(33 to 47).toList:::(58 to 126).toList
    l=Random.shuffle(l)
    var x=ListBuffer[String]()
    var k=0
    (a to b).toList.foreach{e=>{
         if(k==l.length){k=0
         l=Random.shuffle(l)}
         if (e.toInt%8==0){x+=l(k).toChar.toString
           k+=1}
         else{x+=e.toString
             k+=1}}}
    x}

Suggestions for improvements are welcomed.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Here on code golf se we only allow answers which have been at least attempted to be golfed. This means 1 character variable names and removal of spaces android adding a byte count to your answer \$\endgroup\$
    – Blue
    Commented Dec 25, 2016 at 9:05
  • \$\begingroup\$ @muddyfish ok i golfed my code, how is android adding the byte count ? \$\endgroup\$
    – firephil
    Commented Dec 25, 2016 at 15:22
  • \$\begingroup\$ It seems fine to me right now \$\endgroup\$
    – Blue
    Commented Dec 25, 2016 at 15:23
1
\$\begingroup\$

PHP, 163 bytes

$n=range(48,57);$c=array_diff(range(32,126),$n);
foreach(range($a,$b) as $v){if($v%8!=0){echo $v;}
else{for($i=0;$i<strlen($v);$i++){echo chr($c[array_rand($c)]);}}}

Explanation:

  • $n = range(48,57) These are the ASCII codes for numbers, which are in the middle of special characters (32-47) and other characters (58-126).
  • $c = array_diff(range(32,126), $n) Using the $n array, exclude numeric characters and build an array of acceptable ASCII characters.
  • foreach(range($a,$b) as $v) Loop over the range of values from $a to $b (inclusive), as $v inside the loop.
  • if($v % 8 != 0) { echo $v; } Test for $v being evenly divisible by 8 using the mod operator %.
  • else { for($i = 0; $i < strlen($v); $i++) { ... }} If not evenly divisible by 8, loop enough times for the number of digits in the number and print the characters (in the next step).
  • echo chr($c[array_rand($c)]) Print a single character from the acceptable array of ASCII values in $c. array_rand returns an index in the array, so we have to get the actual value at that index using $c[random_key].

I could probably make this smaller by creating $c differently, and the loop to print the ASCII characters feels clunky so I'll continue to ponder how to shorten that.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Thanks Jake! Glad to hear from you! Take a look at my new challenge Random Pixel Poking if you have time too! \$\endgroup\$ Commented Dec 24, 2016 at 19:23
1
\$\begingroup\$

postgresql9.6 251 chars

very long code but postgresql also does it.

do language plpgsql $$ begin for n in a..bloop raise info'%',case when 0=n%8then(select array_to_string(array(select*from(select chr(generate_series(33,126)))t where chr!~'\d'order by random()limit floor(log(n))+1),''))else n::text end;end loop;end;$$

formatted sql is here:

do language plpgsql $$
begin
for n in a..b loop
    raise info '%',
    case when 0 = n % 8 then (
        select array_to_string(array(select * from (
            select chr(generate_series(33, 126))
        ) t where chr !~ '\d' order by random() limit floor(log(n)) + 1), '')
    ) else n::text
    end;
end loop;
end;
$$
\$\endgroup\$
1
\$\begingroup\$

QBIC, 79 bytes

::[a,b|~c%8=0|[_l!c$||_R33,116|~e>47 and e<58|e=e+z]Z=Z+chr$(e)]\Z=Z+!c$]Z=Z+@ 

Skipping the numbers is a costly affair, here's a version that might also randomly select 0-9 for 20 bytes less:

::[a,b|~c%8=0|[len(!c$)|Z=Z+chr$(_r33,126|)]\Z=Z+!c$]Z=Z+@ 

Sample output for 1, 89

1 2 3 4 5 6 7 U 9 10 11 12 13 14 15 M9 17 18 19 20 21 22 23 ^L 25 26 27 28 29 30 
31 <U 33 34 35 36 37 38 39 gH 41 42 43 44 45 46 47 aJ 49 50 51 52 53 54 55 1b 57 58 59 60 
61 62 63 ,C 65 66 67 68 69 70 71 ]; 73 74 75 76 77 78 79 [B 81 82 83 84 85 86 87 Ix 89 

Explanation:

::        Get inputs 'a' and 'b' from the command line
[a,b|     FOR(c=a; c<=b; c++)
~c%8=0|   IF c is cleanly divisible by 8 THEN
 _l!c$|   Take the length (_l) of the string representation (! ... $) of c 
[      |  FOR (d = 1; d<= length(c); d++)
_R33,116| Set e to a random value in the range 33 - 116 (all the printable ascii's - 10)
~e>47     IF e falls between 47
and e<58| and 58 (ASCII code for 0-9) THEN 
e=e+z     e = e + 10 (z == 10 in QBIC)
]         END IF
Z=Z+      Add to Z$
chr$(e)]  ASCII character e
\         ELSE if c is not cleanly divisible by 8
Z=Z+!c$   Add to Z the string representation of c
]         NEXT
Z=Z+@     Add a space to Z$ (@ is an implicitly delimited string literal with 1 significant space)

( Z$ is implicitly printed at end of program )
\$\endgroup\$
1
\$\begingroup\$

05AB1E, 17 bytes

ŸεD8ÖižQžhK¦.rsg£

Takes the input as highest\nlowest, and outputs a list.

Try it online or verify all test cases.

Explanation:

Ÿ                  # Create a list in the range [low (implicit) input, high (implicit) input]
 ε                 # Map each value to:
  D                #  Duplicate the value
   8Öi             #  If it's divisible by 8:
      žQ           #   Push all printable ASCII characters (" " through "~")
        žhK        #   Remove all digits
           ¦       #   Remove the first character (the space)
            .r     #   Randomly shuffle the remaining characters
              s    #   Swap to take the map value again
               g   #   Get its length
                £  #   And leave that many characters from the string
                   # (and implicitly output the resulting list after we're done mapping)
\$\endgroup\$
1
\$\begingroup\$

Japt, 20 bytes

;òV ®%8?Z:EÅk9ò)öZìl

Try it

;òV ®%8?Z:EÅk9ò)öZìl     :Implicit input of integers U & V
 òV                      :Range [U,V]
    ®                    :Map each Z
     %8                  :  Modulo 8
       ?Z:               :  If truthy, return Z, else
;         E              :  Printable ASCII
           Å             :  Slice off first character
            k            :  Remove
             9ò          :    Range [0,9]
               )         :  End remove
                 Zì      :  Digit array of Z
                   l     :  Length
               ö         :  Get that many random characters from the string
\$\endgroup\$
1
\$\begingroup\$

Forth (gforth), 128 bytes

include random.fs
: f 1+ swap do i 8 mod if i . else i 0 <# #s #> 0 do 83 random 33 + dup 47 > 10 * - emit loop ."  "then loop ;

Try it online!

Explanation

Loop from start to end, print number if not multiple of 8, otherwise get the number of digits in the number and print that many random characters followed by a space

Code Explanation

include random.fs          \ include/import the random module
: f                        \ start new word definition
  1+ swap                  \ add 1 to end number, because forth loops are [start, end), and swap order
  do                       \ start counted loop form start to end
    i 8 mod                \ get the remainder of dividing i (loop index) by 8
    if                     \ if true (not 0, therefore not multiple of 8)
      i .                  \ print the index
    else                   \ otherwise
      i 0                  \ convert index to double-length number
      <# #s #>             \ use formatted numeric output to convert number to a string
      0 do                 \ loop from 0 to (string-length - 1)
        84 random          \ get random number between 0 and 83
        33 +               \ add 33
        dup 47 >           \ check if result is larger than 47
        10 * -             \ if it is add 10 to result (results in number in range: 33-47,58-126)
        emit               \ output ascii char corresponding with number
      loop                 \ end inner loop
    ."  "then            \ output a space and then close the if/else
  loop                   \ end the outer loop
;                        \ end the word definition

UnGolfed

I don't usually ungolf my solutions, but this one is long/complicated enough that I think it's needed

include random.fs

\ get the length (in digits) of a number
: num-length 0 <# #s #> nip ;

\ check if a number is a multiple of another
: is-multiple mod 0= ;               

\ get a random printable non-digit ascii char           
: random-char 84 random 33 + dup 47 > 10 * - ;  

\ get a "random" string of printable ascii chars the same length as a number
: rand-str num-length 0 do random-char emit loop space ;

\ print numbers from a to b, replacing multiple of 8 with a random ascii string of the same length
: crazy-eights 1+ swap do i 8 is-multiple if i rand-str else i . then loop ;
\$\endgroup\$
1
\$\begingroup\$

PHP, 130 bytes

function($a,$b){for(;$a<=$b;$a++)echo$a%8?$a:(function($l){while($l--)echo chr(($x=rand(44,128))-($x>58?:11));})(strlen($a))," ";}

Try it online!

Ungolfed:

function c8( $a, $b ) { 
    for( ; $a<=$b; $a++ ) {                // loop between a -> b
        echo $a % 8 ? $a :                 // every 8, call anon func instead of value
            (function($l) {
                while( $l-- ) {            // repeat length of value
                    $x = rand( 44, 128 );  // range size is printable chars [33,47][58,127]
                    $x-= $x > 58 ?: 11;    // Subtract one from x. If x was less than or 
                                           // equal to 58, subtract a further ten from it
                                           // so that it now falls within the 33-47 range
                    echo chr( $x );        // echo ASCII value
                }
            })( strlen( $a ) )," ";
    }
}
\$\endgroup\$
6
  • \$\begingroup\$ Yes, my mistake. Regarding $x-= $x > 58 ?: 11; // subtract 11, if x is less than 58 -- could you elaborate? \$\endgroup\$ Commented Feb 5, 2019 at 22:49
  • \$\begingroup\$ @JonathanFrech in other words we want a number that's between 33-47 or 58-127. So we pick a number that's 58 minus the size of the lower range. If the number is below 58 it's just translated down to the lower range by subtracting the difference. Because of course we can't display numbers (ASCII char 48-57) \$\endgroup\$
    – 640KB
    Commented Feb 5, 2019 at 22:53
  • \$\begingroup\$ The ternary is just a shortcut to doing it. Basically $x > 58 evaluates to 1, and so we either subtract that or 11 from $x. In the case where it's higher, it's offset by the ASCII values in the rand() statement being one higher. You can see that this generates a uniformly random (as uniform as PHP's rand() is capable of) distribution: tio.run/… \$\endgroup\$
    – 640KB
    Commented Feb 5, 2019 at 23:02
  • \$\begingroup\$ I think I know roughly what the Elvis operator does, I just think your comment is misleading. \$\endgroup\$ Commented Feb 5, 2019 at 23:13
  • \$\begingroup\$ I would think it works like Subtract one from x. If x was less than or equal to 58, subtract a further ten from it., no? \$\endgroup\$ Commented Feb 5, 2019 at 23:39
1
\$\begingroup\$

Kotlin, 136 bytes

{r:IntRange->var s=""
for(i in r){for(c in "$i"){var n=java.util.Random().nextInt(83)
if(n>14)n+=10
s+=if(i%8>0)c
else '!'+n}
s+=" "}
s}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Zsh, 67 bytes

for i ({$1..$2})((i%8))||i=`tr -dc !-/:-~</*/ur*|head -c$#i`&&<<<$i

Try it online!

Feels pretty long, but so are most answers to this one.

\$\endgroup\$
0
\$\begingroup\$

Python 2, 180 Bytes

from random import*
def f(a,b):
 for i in range(a,b+1):
  if i%8<1:
   k,i=str(i),''
   for _ in k:i+=choice([chr(j)for j in range(33,48)]+[chr(j)for j in range(57,126)])
  print i

EDIT:

Thanks @Flp.Tkc for realising I hadn't read the task properly.

Thanks @Caleb for pointing out I could use a few to reduce the byte count.

Thanks @Dennis for pointing out about the fact that numbers can't be included.

EDIT 2:

The current version could probably be simplified more than it is.

\$\endgroup\$
0
0
\$\begingroup\$

PowerShell, 82 89 bytes

$a,$b=$args;$a..$b|%{($_,(-join[char[]](33..47+58..127|random -c "$_".Length)))[!($_%8)]}

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ 58..127 does not include the printable ASCII symbols in the lower range 33 (!) to 47 (/). \$\endgroup\$
    – zeppelin
    Commented Dec 25, 2016 at 18:33
  • \$\begingroup\$ @zeppelin true, I didn't think that was a requirement, but re-reading it, I suppose it must be if it's to be a uniform distribution. Updated! \$\endgroup\$
    – briantist
    Commented Dec 25, 2016 at 18:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.