Create a program that prints all whole numbers inclusively between an interval (a, b), and replaces every multiple of 8 in the sequence with a random (uniformly distributed), non-numeric, non-whitespace, printable ASCII character. Assume a < b in all cases. If the number has more than 1 digits, 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:

Pyth (24 bytes) by FryAmTheEggman

Most Popular:

Python 2 (133 bytes) by Heather

share|improve this question
6  
Congrats on making a challenge that combines all the super long things to implement in my golfing language – muddyfish 17 hours ago
    
@muddyfish i mean it is a challenge ;) – Caleb 17 hours ago
    
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 13 hours ago
    
@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 – Caleb 13 hours ago
    
@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 – Caleb 13 hours ago

14 Answers 14

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

Still golfing down.

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

share|improve this answer
    
Won't this only print one random character, even for numbers which have more than one digit? – FryAmTheEggman 2 hours ago
    
you can use s.printable[10:-6] to get the ASCII range you want. – Flp.Tkc 2 hours ago
    
I think that you could use list(map(chr,range(33,127))) instead of s.letters+s.punctuation or even Flp.Tck's suggestion. – nedla2004 1 hour ago
    
@heather for convenience could you provide a link to a try it online or something similar? – Caleb 1 hour ago
1  
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 1 hour ago

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.

share|improve this answer

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
`}
share|improve this answer
    
May I ask why you are outputting the numbers that are divisible by 8? – Caleb 16 hours ago
    
@Caleb Whoops, that was a typo. It was meant to read "not divisible by 8." – Doorknob 16 hours ago

Python 2, 121 120 bytes

import random,string
def f(a,b):print(a,`random.sample(string.printable[10:-6]*a,len(`a`))`[2::5])[a%8<1];f(a+1/(a<b),b)

Terminates with an error.

Try it online!

share|improve this answer

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.

share|improve this answer
    
This is incorrect. The randomly selected characters may not contain digits. – Dennis 1 hour ago
    
@Dennis alright, back to my splicing idea :P Thanks for the heads up – Flp.Tkc 1 hour ago
    
Python 2 seems to be popular contender, i love it! – Caleb 44 mins ago

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)
share|improve this answer
    
Wow, cool! Nice answer. +1 – heather 16 hours ago
    
@heather Thanks! I have a feeling it could be made shorter... – Luis Mendo 16 hours ago

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
share|improve this answer

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.

share|improve this answer

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
share|improve this answer

Bash + jot, 64 bytes

Golfed

seq $1 $2|sed "$[9-$1%8]~8s/.*/a=&;jot -r -s '' -c \${#a} ! ~/e"

Test

>crazy8 115 123
115
116
117
118
119
&Wn
121
122
123

>crazy8 1 16
1
2
3
4
5
6
7
Y
9
10
11
12
13
14
15
ZR
share|improve this answer
    
Could you give is a brief walk through? Also im curious to see what crazy8 8 8 would yield – Caleb 1 hour ago

Pyke, 22 bytes

h1:Fi8%!I`lV~KT>6_<Hs0

Try it here!

Takes input in the form: higher, lower

share|improve this answer
    
Lists are all good! – Caleb 41 mins ago
    
@Caleb Thanks - done – muddyfish 40 mins ago
    
This is interesting, the first case ive seen where 8n, 8n causes an error – Caleb 37 mins ago
    
my bad I misread the output – Caleb 34 mins ago

JavaScript (ES6), 100 bytes

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

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

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

share|improve this answer

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.
share|improve this answer

Python 2, 111 125 Bytes

from random import*
def f(a,b):
 for i in range(a,b+1):
  if i%8<1:i=''.join([chr(randint(58,126))for _ in str(i)])
  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.

share|improve this answer
1  
The random characters cannot include digits, as yours do. And you have to print n random characters where n is the length of the number you are replacing. So this solution is invalid – Flp.Tkc 54 mins ago
    
I believe you can cut the byte count by replacing a,b=input(), input() with def f(a,b) – Caleb 53 mins ago
    
It's still incorrect. The randomly chosen characters cannot be digits. – Dennis 33 mins ago
    
Now you're ignoring all symbols before 0. – Dennis 28 mins ago
    
@Dennis the question never said that all characters have to be able to be selected, it just said a random character – sonrad10 26 mins ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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