# Crazy 8s Code Golf

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

• Congrats on making a challenge that combines all the super long things to implement in my golfing language – Blue Dec 24 '16 at 0:16
• @muddyfish i mean it is a challenge ;) – GracefulLemming Dec 24 '16 at 0:16
• 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)? – FryAmTheEggman Dec 24 '16 at 4:09
• @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 – GracefulLemming Dec 24 '16 at 4:14
• @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 – GracefulLemming Dec 24 '16 at 4:15

## Pyke, 22 21 bytes

h1:Fi8%!IlV~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(^)

• Lists are all good! – GracefulLemming Dec 24 '16 at 16:53
• This is interesting, the first case ive seen where 8n, 8n causes an error – GracefulLemming Dec 24 '16 at 16:57
• my bad I misread the output – GracefulLemming Dec 24 '16 at 16:59

# Python 2, 119 bytes

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


Try it online!

• To quote Flp.Tkc: "One does not simply outgolf Dennis" – GracefulLemming Dec 24 '16 at 19:07

# 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!

• 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/… – Dennis Dec 24 '16 at 16:16
• @Dennis, thank you, that took off 7 bytes! – heather Dec 24 '16 at 16:59

## 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
}

• May I ask why you are outputting the numbers that are divisible by 8? – GracefulLemming Dec 24 '16 at 0:56
• @Caleb Whoops, that was a typo. It was meant to read "not divisible by 8." – Doorknob Dec 24 '16 at 1:03

# 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.

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

## 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.

# 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.

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

# 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


# 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....

• The replacement chars should be non-numerical – LarsW Dec 24 '16 at 22:08
• @LarsW Somehow missed that, thanks – ETHproductions Dec 25 '16 at 1:50

# 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)

• Wow, cool! Nice answer. +1 – heather Dec 24 '16 at 0:54
• @heather Thanks! I have a feeling it could be made shorter... – Luis Mendo Dec 24 '16 at 0:55

# Pyth, 24 bytes

jm?%d8dsmO-r\~\ jkUTd}F


Try it online!

### Explanation:

jm?%d8dsmO-r\~\ jkUTd}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


# Bash + apg, 64, 76 bytes

EDITS:

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

Golfed

seq $1$2|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!

• Could you give is a brief walk through? Also im curious to see what crazy8 8 8 would yield – GracefulLemming Dec 24 '16 at 16:06
• @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). – zeppelin Dec 24 '16 at 20:08

# 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.

# 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.

• Thanks Jake! Glad to hear from you! Take a look at my new challenge Random Pixel Poking if you have time too! – GracefulLemming Dec 24 '16 at 19:23

## 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;$$


## 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. # 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 }  • You can save 3 bytes if you change to a newline separator (puts instead of printf). – O.O.Balance Apr 13 '18 at 9:12 • It's more fun to play with your solution :-) – jxh Apr 13 '18 at 18:51 # 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 }  # 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  • range [0,127] does not conform to spec: "non-numeric, non-whitespace, printable ASCII" – O.O.Balance Apr 4 '18 at 14:59 • @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. – Kevin Cruijssen Apr 4 '18 at 15:27 • No, I think your comment is fine. My bad :) – O.O.Balance Apr 4 '18 at 15:46 # 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  # 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. • 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 – Blue Dec 25 '16 at 9:05 • @muddyfish ok i golfed my code, how is android adding the byte count ? – firephil Dec 25 '16 at 15:22 • It seems fine to me right now – Blue Dec 25 '16 at 15:23 # 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. # PowerShell, 82 89 bytes $a,$b=$args;$a..$b|%{($_,(-join[char[]](33..47+58..127|random -c "$_".Length)))[!($_%8)]}  Try it online! • 58..127 does not include the printable ASCII symbols in the lower range 33 (!) to 47 (/). – zeppelin Dec 25 '16 at 18:33 • @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! – briantist Dec 25 '16 at 18:47 ## 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 )


# 05AB1E, 17 bytes

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


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

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)


# 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


# 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
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 ;


# 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 ) )," ";
}
}

• Yes, my mistake. Regarding $x-=$x > 58 ?: 11; // subtract 11, if x is less than 58 -- could you elaborate? – Jonathan Frech Feb 5 '19 at 22:49
• @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) – 640KB Feb 5 '19 at 22:53
• 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/… – 640KB Feb 5 '19 at 23:02
• I think I know roughly what the Elvis operator does, I just think your comment is misleading. – Jonathan Frech Feb 5 '19 at 23:13
• 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? – Jonathan Frech Feb 5 '19 at 23:39

# 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!