14
\$\begingroup\$

Anyone here a die-hard Bethesda fan? Maybe you prefer Obsidian Entertainment? Well, if you're either of those things than the following picture should be relatively familiar to you.

The fallout terminal.

I've taken the liberty of preparing a rather unique ASCII-Art challenge, so here's the first clue as to what I'm going to have you do:

  _____________________________________________________
 /                                                     \ 
|     _____________________________________________     |
|    |                                             |    |
|    | Welcome to ROBCO Industries (TM) Termlink   |    |
|    | Password Required                           |    |
|    | Attempts Remaining:                         |    |
|    |                                             |    |
|    | 0x01                 | 0x0D                 |    |
|    | 0x02                 | 0x0E                 |    |
|    | 0x03                 | 0x0F                 |    |
|    | 0x04                 | 0x10                 |    |
|    | 0x05                 | 0x11                 |    |
|    | 0x06                 | 0x12                 |    |
|    | 0x07                 | 0x13                 |    |
|    | 0x08                 | 0x14                 |    |
|    | 0x09                 | 0x15                 |    |
|    | 0x0A                 | 0x16                 |    |
|    | 0x0B                 | 0x17                 |    |
|    | 0x0C                 | 0x18                 |    |
|    |_____________________________________________|    |
|                                                       |
\_______________________________________________________/ 
       \_______________________________________/        

This is a very basic (blank) template for the RobCo Fallout terminal design in pure ASCII, your job will be to:

  • First, generate this template.
  • Then, given a list of strings l and a number 0 <= n <= 4 to fill it up!

The two dynamic parts of a fallout hacking terminal are:

The Number of Attempts

  • The number of attempts you have remaining (indicated by space delimited boxes.
    • For the purpose of this challenge you will be using X instead of .

The Passwords

  • The passwords, defined by l, are interspersed with random printable ASCII symbols.
  • The passwords, as you can tell by the example, can wrap multiple rows (NAMES).
  • All passwords in the terminal screen should have an equal chance of being anywhere.
  • All passwords can be expected to be of equal length, though this doesn't matter.
  • The list of symbols usable to separate passwords are: !"#$%&'()*+/:;<=>?@[\]^_{|}.
  • All passwords in l must be of equal length.
  • PASSWORDS MUST HAVE THE POTENTIAL TO WRAP BETWEEN BOTH COLUMNS.
    • This also goes for rows, but only to a higher byte address (0x18->0x01 is invalid).
  • The display space for passwords on either side is 15 wide (with a space on either side).
    • You may assume no words in l will be longer than this.
  • Passwords are alphabetical only, meaning only letters.

Example:

l = ["SMART","ENACT","SWORE","PITYS","SMELL","CARTS","RACES"], n = 4

  _____________________________________________________
 /                                                     \ 
|     _____________________________________________     |
|    |                                             |    |
|    | Welcome to ROBCO Industries (TM) Termlink   |    |
|    | Password Required                           |    |
|    | Attempts Remaining: X X X X                 |    | # N = 4 drives these X's.
|    |                                             |    |
|    | 0x01 $?_/%$ENACT||"} | 0x0D TYS"_'$\#|^%&{} |    |
|    | 0x02 }:!*@{/_<"[]#>; | 0x0E #{!"^&\]'|}_[$% |    |
|    | 0x03 $%&'()*+/:;<\_' | 0x0F }|[(%SMELL/_$@( |    |
|    | 0x04 ^SMART(!@$*'^_@ | 0x10 []_#!"{|}'%$\&^ |    |
|    | 0x05 (*@#%}*(!%)^(_! | 0x11 %$}[!\#'^&_]{|" |    |
|    | 0x06 $%&'()*+/:;<_@) | 0x12 \SWORE|%'_!}\^" |    |
|    | 0x07 "/')=*%!&>#<:$+ | 0x13 ^{['&$|!_]%\"#} |    |
|    | 0x08 ;'*$&"(<%!#)RAC | 0x14 ']!|^#[$"_\}&{% |    |
|    | 0x09 ES:($&';%#+"<*/ | 0x15 @)($!CARTS*!@$_ |    |
|    | 0x0A ;'*$&"(<%!#)/+: | 0x16 !#%${"'}&[]^|_\ |    |
|    | 0x0B |'_!}$\%["#^{&] | 0x17 ]"_#$&}^%[{|\'! |    |
|    | 0x0C #{!"^&\]'|}_[PI | 0x18 _![&#{$%\^'|}"] |    | # Notice how PITYS wrapped.
|    |_____________________________________________|    |
|                                                       |
\_______________________________________________________/ 
       \_______________________________________/        

If n = 2 on the same example:

  _____________________________________________________
 /                                                     \ 
|     _____________________________________________     |
|    |                                             |    |
|    | Welcome to ROBCO Industries (TM) Termlink   |    |
|    | Password Required                           |    |
|    | Attempts Remaining: X X                     |    | # N = 2 drives these X's.
|    |                                             |    |
|    | 0x01 $?_/%$ENACT||"} | 0x0D TYS"_'$\#|^%&{} |    |
|    | 0x02 }:!*@{/_<"[]#>; | 0x0E #{!"^&\]'|}_[$% |    |
|    | 0x03 $%&'()*+/:;<\_' | 0x0F }|[(%SMELL/_$@( |    |
|    | 0x04 ^SMART(!@$*'^_@ | 0x10 []_#!"{|}'%$\&^ |    |
|    | 0x05 (*@#%}*(!%)^(_! | 0x11 %$}[!\#'^&_]{|" |    |
|    | 0x06 $%&'()*+/:;<_@) | 0x12 \SWORE|%'_!}\^" |    |
|    | 0x07 "/')=*%!&>#<:$+ | 0x13 ^{['&$|!_]%\"#} |    |
|    | 0x08 ;'*$&"(<%!#)RAC | 0x14 ']!|^#[$"_\}&{% |    |
|    | 0x09 ES:($&';%#+"<*/ | 0x15 @)($!CARTS*!@$_ |    |
|    | 0x0A ;'*$&"(<%!#)/+: | 0x16 !#%${"'}&[]^|_\ |    |
|    | 0x0B |'_!}$\%["#^{&] | 0x17 ]"_#$&}^%[{|\'! |    |
|    | 0x0C #{!"^&\]'|}_[PI | 0x18 _![&#{$%\^'|}"] |    | # Notice how PITYS wrapped.
|    |_____________________________________________|    |
|                                                       |
\_______________________________________________________/ 
       \_______________________________________/        

These examples were manually crafted, so the distribution is not randomized, sorry.


This is , lowest byte-count will be the accepted winner. I will bounty this after 3 days if no answers have been submitted for a total of 250 REP.

\$\endgroup\$
10
  • \$\begingroup\$ Quick! No one answer for 3 days! (kidding). This is my new favorite ascii-art challenge. \$\endgroup\$
    – nmjcman101
    Aug 9, 2017 at 21:43
  • 2
    \$\begingroup\$ @nmjcman101 what was your last favorite? \$\endgroup\$ Aug 9, 2017 at 22:05
  • \$\begingroup\$ What does the NAMES in the 2nd bullet point mean? "All passwords can be expected to be of equal length, though this doesn't matter." or "All passwords in l must be of equal length."? It may just be me being blind (again!) but I don't see RACES in either output - should we take this to mean that there should be a possibility of a password not being used? Is Math.random (and equivalents) sufficiently random for the purposes of this challenge? \$\endgroup\$
    – Shaggy
    Aug 9, 2017 at 22:31
  • 2
    \$\begingroup\$ Do there have to be non-alphanumeric spacers between two passwords or is it fine if they generate right next to each other (non-overlapping)? \$\endgroup\$
    – hyper-neutrino
    Aug 9, 2017 at 22:52
  • 5
    \$\begingroup\$ Do the passwords need to have the possibility of wrapping right-around from 0x18 to 0x01? \$\endgroup\$ Aug 10, 2017 at 0:48

5 Answers 5

6
\$\begingroup\$

JavaScript (ES8), 575 568 564 bytes

Saved 3 bytes thanks to @Shaggy

Takes input in currying syntax (r)(a), where r is the number of remaining attempts and a is the array of passwords.

r=>a=>[...C=`!"#[]^$%&'*+;<{}=`].reduce((s,c)=>(x=s.split(c)).join(x.pop()),`  "%%__
 /;;# \\ 
[ "} $Welcome to ROBCO Industries (TM) Termlink'!Password Required#}'!Attempts Remaining:${" X".repeat(r).padEnd(9)};[$^1=^D<2=^E<3=^F<4*0<5*1<6*2<7*3<8*4<9*5<A*6<B*7<C*8='+"[|
|;;#'|
\\"{_/ 
}'\\&%/= ]]]]] | }' {%%%<='+ ^#}}}+|
[|*=0x1'   "{{{%___$+;#}} !^0x0]ZZZ[|}#;}"&{![+ `).replace(/Z/g,(c,i)=>a.join``[(i%58>>5?y++:x++)%L],x=(R=n=>Math.random()*n|0)(L=360),y=x+180,[...Array(L-(n=a.sort(_=>R(3)-1).length)*a[0].length)].map(_=>a[R(n)]+=(C+`>?@()/:\\_|`)[R(27)]))

Syntax highlighter disabled on purpose. It has no clue what to do with that.

Demo

let f =

r=>a=>[...C=`!"#[]^$%&'*+;<{}=`].reduce((s,c)=>(x=s.split(c)).join(x.pop()),`  "%%__
 /;;# \\ 
[ "} $Welcome to ROBCO Industries (TM) Termlink'!Password Required#}'!Attempts Remaining:${" X".repeat(r).padEnd(9)};[$^1=^D<2=^E<3=^F<4*0<5*1<6*2<7*3<8*4<9*5<A*6<B*7<C*8='+"[|
|;;#'|
\\"{_/ 
}'\\&%/= ]]]]] | }' {%%%<='+ ^#}}}+|
[|*=0x1'   "{{{%___$+;#}} !^0x0]ZZZ[|}#;}"&{![+ `).replace(/Z/g,(c,i)=>a.join``[(i%58>>5?y++:x++)%L],x=(R=n=>Math.random()*n|0)(L=360),y=x+180,[...Array(L-(n=a.sort(_=>R(3)-1).length)*a[0].length)].map(_=>a[R(n)]+=(C+`>?@()/:\\_|`)[R(27)]))

O.innerText = f(3)(["SMART","ENACT","SWORE","PITYS","SMELL","CARTS","RACES"])
<pre id=O>

\$\endgroup\$
3
  • \$\begingroup\$ Could you save anything using ES8 to populate the attempts like so: Attempts Remaining:${" X".repeat(r).padEnd(8)}? \$\endgroup\$
    – Shaggy
    Aug 10, 2017 at 11:40
  • 1
    \$\begingroup\$ @Shaggy That does save 3 bytes. Thanks! \$\endgroup\$
    – Arnauld
    Aug 10, 2017 at 11:53
  • \$\begingroup\$ Welcome to ROBCO Industries (TM) Termlink'!Password Required#}'!Attempts Remaining: oof... I should've paraphrased to save non-golfing langs bytes. \$\endgroup\$ Aug 11, 2017 at 13:35
4
\$\begingroup\$

SOGL V0.12, 225 bytes

R“EC"+w╗─║Z⁰2BΥø‘▓"▲╔⁸‘'²∙+"⅟Δλ≤LK⅟ΗΠ.JN║«⁸⅟‘▓+╬⁷"№D↓tι▲‛Q─Ρδν∙υ4Ρψ▲¦‽↑√Ε┐Ζ5↔‛⅟≤š▼¦⁾○ΔΡ%³‘ū91 tž85ž.ΖX Ο'⁹7žø]Xe@*c{leκψI1ž}_:@øŗ⁄c∑⁄≠}l{"T-)⅞↑°Χpjζ⅓īa0ε+Μ‛⁶ρ\=↔⅟¹‘ψ}¹K@Gŗ'¹nο²²Z+8«m«ο+I{@∑"0x0”Κ}¹6«n_'⁷1ž'⁵16«┐∙ž'⁸4 19∙ž89╬5

Try it Here!
Expects array input on the stack and the number input an an input, so →" is added in the online program for ease-of-use.

\$\endgroup\$
4
\$\begingroup\$

Perl 5, 588 560 + 1 (-a) = 589 561 bytes

Cut 28 bytes with the suggestions Dom pointed out

$,=$/;$_=" X"x pop@F;say"  "."_"x53," /".$"x53 ."\\",$q="|     ".'_'x45 ."     |",$e=($b="|    |").$"x45 .$b,"$b Welcome to ROBCO Industries (TM) Termlink   $b
$b Password Required".$"x27 .$b,"$b Attempts Remaining:$_".$"x(25-length).$b,$e;map{$s.=(grep/[^\w,.`-]|_/,map{chr}33..125)[rand 27]}1..360;($t=substr$s,$r=rand 360-($l=length),$l,$_)=~/[a-z]/i&&(substr$s,$r,$l,$t)&&push@F,$_ while$_=pop@F;@o=$s=~/.{15}/g;printf"$b 0x0%X %s | 0x%02X %s $b\n",$_,$o[$_-1],$_+12,$o[$_+11]for 1..12;say$b.'_'x45 .$b,$q=~y/_/ /r,$q=" \\"."_"x54 ."/",$"x6 .$q=~s/_{15}//r

Try it online!

Previously:

$,=$/;$_=" X"x pop@F;say"  "."_"x53," /".($"x53)."\\",$q="|     ".('_'x45)."     |",$e=($b="|    |").($"x45).$b,"$b Welcome to ROBCO Industries (TM) Termlink   $b
$b Password Required".($"x27).$b,"$b Attempts Remaining:$_".($"x(25-length)).$b,$e;$s=join'',map{(split//,'!"#$%&\'()*+/:;<=>?@[]^_{|}\\')[int rand 27]}1..360;while($_=pop@F){if(($t=substr$s,$r=rand 360-($l=length),$l,$_)=~/[a-z]/i){substr$s,$r,$l,$t;push@F,$_}}@o=$s=~/.{15}/g;printf"$b 0x0%X %s | 0x%02X %s $b\n",$_,$o[$_-1],$_+12,$o[$_+11]for 1..12;say$b.('_'x45).$b,$q=~y/_/ /r,$q=" \\".("_"x54)."/",($"x6).$q=~s/_{15}//r

Try it online!

Input is on one line, space separated: first the strings, then the number

How?

$,=$/;          # delimiter between fields is newline
$_=" X"x pop@F; # set number of attempts left
say             # output the header
"  "."_"x53,
" /".($"x53)."\\",
$q="|     ".('_'x45)."     |",
$e=($b="|    |").($"x45).$b,
"$b Welcome to ROBCO Industries (TM) Termlink   $b
$b Password Required".($"x27).$b,
"$b Attempts Remaining:$_".($"x(25-length)).$b,
$e;
$s=join'',map{(split//,'!"#$%&\'()*+/:;<=>?@[]^_{|}\\')[int rand 27]}1..360; # create random string long enough for entire screen
while($_=pop@F){  # for each given string
if(($t=substr$s,$r=rand 360-($l=length),$l,$_) # attempt to insert it
=~/[a-z]/i)                                    # but check if it overlaps another string
{substr$s,$r,$l,$t;                            # if it does, take it out
push@F,$_}}                                    # and put it back in line
@o=$s=~/.{15}/g;                               # split "memory dump" into chunks
printf"$b 0x0%X %s | 0x%02X %s $b\n",$_,$o[$_-1],$_+12,$o[$_+11]for 1..12; #output the grid
say                                            # output the footer
$b.('_'x45).$b,$q=~y/_/ /r,
$q=" \\".("_"x54)."/",
($"x6).$q=~s/_{15}//r
\$\endgroup\$
1
  • \$\begingroup\$ Nice answer to a complex problem! You should be able to save almost 30 bytes by removing the brackets around the repetition operator, you can add a space so the . isn't used as a decimal point. Also to get the punctuation you can use something like (grep/[^\w,.`-]|_/,map{chr}33..125) and you don't need to call int on an array index! Changing the while loop to postfix and using && instead of if should save a few too. When you're building $s, if you have $s.= inside the map instead of using join drops a few more. Hope that helps! \$\endgroup\$ Aug 10, 2017 at 7:37
4
\$\begingroup\$

Python 3, 585 bytes

from random import*
def f(l,n,r=range):
	u,c='_ ';a=[choice('!"#$%&\'()*+/:;<=>?@[\\]^_{|}')for i in c*360];L=len(l[0]);i={*r(360-len(l[0]))};p=lambda x:'0x%02X'%x+c+''.join(a[15*x:][:15])
	for q in l:s=choice([*i]);a[s:s+L]=q;i-={*r(s+~L,s+-~-~L)}
	return'''  %s
 /%s\\
|# %s #|
?%s?
? Welcome to ROBCO Industries (TM) Termlink   ?
? Password Required   ######?
? Attempts Remaining:%-25s?
?%s?
%%s?%s?
|%s|
\%s/
#   \%s/'''.replace('?','|#|').replace('#',c*4)%(u*53,c*53,u*45,c*45,' X'*n,c*45,u*45,c*55,u*55,u*39)%('|    | %s | %s |    |\n'*12)%sum([(p(x),p(x+12))for x in r(12)],())

Try it online!

-70 bytes thanks to Jonathan Allan
-9 bytes thanks to myself (finally!)
-72 bytes thanks to notjagan

\$\endgroup\$
5
  • \$\begingroup\$ Another 35 bytes off! \$\endgroup\$
    – notjagan
    Aug 10, 2017 at 2:48
  • \$\begingroup\$ And 15 more. \$\endgroup\$
    – notjagan
    Aug 10, 2017 at 2:54
  • \$\begingroup\$ 16 more removed! (there has to be better way to do this than a bunch of comments) \$\endgroup\$
    – notjagan
    Aug 10, 2017 at 3:03
  • \$\begingroup\$ Another 6 bytes off by half-reverting one of my other changes (I really should stop commenting). \$\endgroup\$
    – notjagan
    Aug 10, 2017 at 5:06
  • \$\begingroup\$ @notjagan I don't mind comments :) Thanks! \$\endgroup\$
    – hyper-neutrino
    Aug 10, 2017 at 15:39
2
\$\begingroup\$

JavaScript (ES8), 639 bytes

(w,n,r=i=>Math.random()*i|0,s=b=>{for(i=b[k];i;i--)[b[i-1],b[j]]=[b[j=r(i)],b[i-1]]},a=Array(360-w[k="length"]*--w[0][k]),m=[...a].map((j,i)=>~(j=d.slice(0,w[k]).indexOf(i))?w[j]:`!"#$%&'()*+/:;<=>?@[\\]^_{|}`[r(27)],s(w),s(d=[...a.keys()])).join``.match(/.{15}/g).map((v,i)=>"0x"+(i+1).toString(16).padStart(2,0)+" "+v))=>`  _53
 / 53\\
| 5_45 5|
${["","Welcome to ROBCO Industries (TM) Termlink","Password Required","Attempts Remaining:"+" X".repeat(n),"",...m.slice(0,12).map((x,i)=>x+" | "+m[i+12])].map(x=>"| 4| "+x.padEnd(43)+" | 4|").join`
`}
| 4|_45| 4|
| 55|
\\_55/
 7\\_39/`.replace(/[_ ]([1-9]+)/g,(m,n)=>m[0].repeat(n))

The hex labels are in lowercase; if uppercase was required, that would be an additional 14 bytes for .toUpperCase().

Test Snippet

Better viewed over on CodePen.

\$\endgroup\$
1
  • \$\begingroup\$ You can save a byte by currying the 2 parameters and moving your variables into the first repeat. \$\endgroup\$
    – Shaggy
    Aug 10, 2017 at 20:31

Your Answer

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

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