Crazy 8s Code Golf


34

Utwórz program, który drukuje wszystkie liczby całkowite między interwałami (a, b)i zastępuje wielokrotności 8 w sekwencji losowymi (równomiernie rozmieszczonymi, niezależnymi od innych znaków), nienumerycznymi, niebiałymi znakami drukowalnymi ASCII.

Załóżmy 0 <a <b we wszystkich przypadkach.

Jeśli liczba ma więcej niż 1 cyfrę, upewnij się, że liczba znaków w zastępstwie jest zgodna!

Przykłady:

(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

Nie-przykłady:

(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

To jest kod golfowy, więc wygrywa najkrótszy kod w bajtach!

Aktualny zwycięzca:

Pyke (21 bajtów) przez błotniaka

Najbardziej popularny:

Python 2 (119 bajtów) Dennisa


11
Gratuluję podjęcia wyzwania, które łączy w sobie wszystkie bardzo długie rzeczy do zaimplementowania w moim języku golfowym
Blue

1
@muddyfish mam na myśli, że jest to wyzwanie;)
GracefulLemming

Nie jestem pewien, czy coś mi brakuje, ale czy losowe postacie powinny być unikalne, czy nie? Na przykład, jeśli dane wejściowe wynosiły 16, 16, to czy wynikiem może być aa ? Jeśli tak nie jest, to co, jeśli liczba ma więcej niż 85 cyfr (zakładając, że poprawnie policzyłem)?
FryAmTheEggman

@FryAmTheEggman każda postać powinna być wyjątkowa głównie, ale jeśli „a” i „a” są losowo wybierane kolejno, to jest w porządku, ale nie powinno się to zdarzać we wszystkich przypadkach, ponieważ prawdopodobieństwo jest tak niskie
GracefulLemming

@FryAmTheEggman i przypadek 16, 16 w innych przykładach zwraca 0 lub 2 losowe znaki, ale nie martw się o tę sprawę, ponieważ zawsze będzie ona zawsze mniejsza niż b
GracefulLemming

Odpowiedzi:


4

Pyke, 22 21 bajtów

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

Wypróbuj tutaj!

Bierze wkład w postaci: 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(^)

Listy są dobre!
GracefulLemming

To ciekawe, pierwszy przypadek, w którym widziałem, gdzie 8n, 8n powoduje błąd
GracefulLemming

mój zły, źle odczytałem wynik
GracefulLemming

11

Python 2, 126 bajtów

Wypróbuj 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

Ogromne podziękowania dla Flp.Tkc i EasterlyIrk za całą ich pomoc!


2
Możesz użyć b/azamiast a<=bi nie potrzebujesz ;na końcu. Również import random,stringoszczędza kilka bajtów. tio.run/nexus/…
Dennis

@Dennis, dziękuję, że wziąłeś 7 bajtów!
wrzos


6

zsh, 100 98 bajtów

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

Dwa argumenty wejściowe są przekazywane jako argumenty wiersza poleceń, a liczby są wyprowadzane w osobnych wierszach.

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

Czy mogę zapytać, dlaczego podajesz liczby, które można podzielić przez 8?
GracefulLemming

1
@Caleb Whoops, to była literówka. Chodziło o to, aby czytać „ nie podzielna przez 8.”
Klamka

5

Mathematica, 96 bajtów

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

Wyjaśnienie

Dla danych wejściowych mi n:

Range@##

Generować {m, m + 1, m + 2, ... , n}

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

Dla wszystkich liczb, które można podzielić przez 8 (zadzwoń a), zastosuj tę zasadę zastępowania:

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

Uzyskaj listę wszystkich drukowalnych znaków ASCII, z wyjątkiem cyfr.

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

Pseudolosowo wybieraj Floor[Log10[a] + 1]znaki z listy, umożliwiając duplikaty.

<>""

Dołącz do postaci.


inne podejście do 96 bajtów przy użyciuFromCharacterCode (r=Range)@##/.a_?(8∣#&):>FromCharacterCode[Join[33~r~47,58~r~127]~RandomChoice~⌊Log10@a+1⌋]<>""&
jaeyong śpiewał

5

R, 73 bajty

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

Odczytuje dane wejściowe ze standardowego wejścia i zastępuje liczby podzielne przez 8równomiernie wybraną próbkę znaków ascii w zakresie 32...47, 58...126. Aby narysować losową próbkę, potrzebujemy wektora znaków, niestety intToUtf8()zwraca on jeden ciąg, a nie wektor, więc musimy również wektoryzować go w całym zakresie za pomocą sapply.


5

Python 2, 126 bajtów

(nie chodzi tylko o Dennisa)

Widząc, że dużo pracy nad odpowiedzią Heather, pomyślałem, że opublikuję również własne rozwiązania.

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

Jest to funkcja, która pobiera dwa argumenty i drukuje bezpośrednio do STDOUT.

127 bajtów

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

Jest to anonimowa funkcja anonimowa - do użycia, przypisania do zmiennej (np. f), A następnie wywołania za pomocą f(a, b). Zwraca to wynik jako listę.


To jest niepoprawne. Losowo wybrane znaki nie mogą zawierać cyfr.
Dennis

@Dennis w porządku, wracając do mojego pomysłu na łączenie: P Dzięki za heads-up
FlipTack

Python 2 wydaje się być popularnym kandydatem, uwielbiam go!
GracefulLemming

4

Pip , 28 bajtów

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

Pobiera liczby jako argumenty wiersza poleceń i wyświetla listę wyników oddzieloną od nowej linii. Wypróbuj online!

Wyjaśnienie:

                              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

4

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


1
The replacement chars should be non-numerical
LarsW

@LarsW Somehow missed that, thanks
ETHproductions

3

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

@heather Thanks! I have a feeling it could be made shorter...
Luis Mendo

3

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

3

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

@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

2

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.

1

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.


1
Thanks Jake! Glad to hear from you! Take a look at my new challenge Random Pixel Poking if you have time too!
GracefulLemming

1

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

1

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.


1

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

It's more fun to play with your solution :-)
jxh

1

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
}

This conversation can be continued in chat.
DJMcMayhem

1

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

@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

No, I think your comment is fine. My bad :)
O.O.Balance

1

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

1

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.


1
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

@muddyfish ok i golfed my code, how is android adding the byte count ?
firephil

It seems fine to me right now
Blue

0

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.


0

PowerShell, 82 89 bytes

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

Try it online!


1
58..127 does not include the printable ASCII symbols in the lower range 33 (!) to 47 (/).
zeppelin

@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

0

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 )

0

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)

0

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

0

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 ;

0

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

@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

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

I think I know roughly what the Elvis operator does, I just think your comment is misleading.
Jonathan Frech

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.