Name of Frankenstein's Monster

15

2

Introduction:

Since it's almost Halloween, I was just thinking of some random Halloween-themed challenges. Eventually I was reading through Frankenstein's wikipedia page, and came across the following text:

The creature

Part of Frankenstein's rejection of his creation is the fact that he does not give it a name, which causes a lack of identity. Instead it is referred to by words such as "wretch", "monster", "creature", "demon", "devil", "fiend", and "it". When Frankenstein converses with the creature in Chapter 10, he addresses it as "vile insect", "abhorred monster", "fiend", "wretched devil", and "abhorred devil".

source

Challenge:

Given two integers (year and chapter), output a string based on the following rules:

  1. If the year is less than 1818: output an empty string
  2. If the year is exactly 1818 and the chapter is below 10: output a random string from the list ["wretch", "monster", "creature", "demon", "devil", "fiend", "it"]
  3. If the year is exactly 1818 and the chapter is 10 or higher: output a random string from the list ["vile insect", "abhorred monster", "fiend", "wretched devil", "abhorred devil"]
  4. Is the year above 1818 (and thus the book was published), return "Frankenstein's Monster".

Challenge rules:

  • You can choose whether to output in lowercase, uppercase, or a combination.
  • The year will always be in the range 1500-2017
  • The chapter will always be in the range 1-24 (if I googled correctly, the book has 24 chapters)
  • Instead of outputting an empty string for option 1, you are also allowed to output null, undefined, false, 0, or any other value of your choice not part of the other three options (please specify what you've used in your answer).
  • The output may not contain any leading or trailing spaces/tabs, nor any leading new-lines. It may contain one optional trailing new-line.

General rules:

  • This is , so shortest answer in bytes wins.
    Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
  • Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters, full programs. Your call.
  • Default Loopholes are forbidden (especially 'Fake random numbers').
  • If possible, please add a link with a test for your code.
  • Also, please add an explanation if necessary.

Test cases:

year,chapter possible outputs:

1700,1       ""; null; undefined; false; 0; etc.
1700,12      ""; null; undefined; false; 0; etc.
1817,10      ""; null; undefined; false; 0; etc.
1818,1       "wretch"; "monster"; "creature"; "demon"; "devil"; "fiend"; "it"
1818,9       "wretch"; "monster"; "creature"; "demon"; "devil"; "fiend"; "it"
1818,10      "vile insect"; "abhorred monster"; "fiend"; "wretched devil"; "abhorred devil"
1818,11      "vile insect"; "abhorred monster"; "fiend"; "wretched devil"; "abhorred devil"
1818,18      "vile insect"; "abhorred monster"; "fiend"; "wretched devil"; "abhorred devil"
1819,1       "Frankenstein's Monster"; "frankenstein's monster"; "FRANKENSTEIN'S MONSTER"
1819,18      "Frankenstein's Monster"; "frankenstein's monster"; "FRANKENSTEIN'S MONSTER"
2017,24      "Frankenstein's Monster"; "frankenstein's monster"; "FRANKENSTEIN'S MONSTER"

Kevin Cruijssen

Posted 2017-10-23T14:30:48.540

Reputation: 67 575

Answers

3

Perl 5, 156 153 151 bytes

-3 bytes thanks to DomHastings.

Run with -p

$_=($d=devil,$m=monster,$w=wretch,<"{creature,demon,it,fiend,vile insect,{abhorr,$w}ed {$d,$d,$m},Frankenstein's $m}">)[/818/?6*/,../+rand 7:$_/606-5]

This output distribution is non-uniform, which is accepted by default. Specifically, if the date is 1818 and the chapter is ≥10, the names “abhorred devil” and “abhorred monster” are weighted twice as much. This lets me use rand 7 for both cases, even though the lists are of different sizes.

The output for years before 1818 is “wretched monster”. Despite some similarities, this string is not part of any of the other three options, making it okay to use.

This fails for years outside of the 1212—2424 range, but luckily the year is guaranteed by the rules to be in the 1500—2017 range.

Try it online!

Grimmy

Posted 2017-10-23T14:30:48.540

Reputation: 12 521

I didn't know brace expansion was a thing in Perl at all... Using that approach, there's a great solution for the known knowns challenge! Try it online!

– Dom Hastings – 2017-10-27T07:53:42.923

@DomHastings Ooh I didn’t know you could quote spaces like that. That’s -3 bytes here! – Grimmy – 2017-10-27T08:34:27.427

Glad I was able to help! I'll definitely have to try and remember this, I guess it's because <...> assumes globs? – Dom Hastings – 2017-10-27T08:38:56.063

1<> is either readline or glob, depending on… stuff (classic Perl: the grammar is ambiguous, but the parser tries to DWYM). When it’s a glob, it closely mimics shell globs, including the brace expansion that’s a common feature in shells. – Grimmy – 2017-10-27T09:45:21.403

Could you perhaps add a TIO-link to your answer. :) It's currently the shortest answer, but I just want to make sure everything works before I accept it as the shortest. – Kevin Cruijssen – 2017-11-13T13:43:30.257

@KevinCruijssen I added a TIO link. Note that the TIO code uses -l for aesthetic reasons only (without it, the outputs are all concatenated on a single line, making them hard to read). Since the trailing newline is optional, that flag shouldn’t be counted in my answer’s score. – Grimmy – 2017-11-13T16:23:05.777

@Grimy Thanks for adding the TIO link. And funny how you output wretched monster as <1818 output. :) But you're indeed right, it's not part of the other options, so indeed allowed. I've accepted your answer as the shortest. – Kevin Cruijssen – 2017-11-14T07:44:09.713

9

Python 2, 227 220 214 bytes

lambda y,c:[[choice([["wretch",m,"creature","demon",d,F,"it"],["vile insect",a+m,F,"wretched "+d,a+d]][c>9]),"Frankenstein's "+m][y>1818],0][y<1818]
from random import*
m,d,F,a='monster','devil','fiend',"abhorred "

Try it online!

TFeld

Posted 2017-10-23T14:30:48.540

Reputation: 19 246

1You can save 6 more bytes by putting 'abhorred ' to the list at the bottom as well, since it's been used twice. ('wretch' is also possible, but byte-count stays the same.) – Kevin Cruijssen – 2017-10-23T15:07:39.710

6

Perl 5, 172 bytes

171 bytes code + 1 for -p.

@a=<><10?($}=wretch,$M=monster,creature,demon,$D=devil,fiend,it):("vile insect",($A="abhorred ").$M,fiend,"$}ed $D",$A.$D);$_=($a[rand@a],"frankenstein's $M",0)[$_<=>1818]

Try it online!

Explanation

Pretty standard, only slightly unsual thing is using the 'spaceship operator' (<=>) with 1818 to return -1, 0, or 1, if the input $_ is less than, equal to, or greater than 1818 to return the last, first, or second index of the source data. Also, I like the fish operator!

Dom Hastings

Posted 2017-10-23T14:30:48.540

Reputation: 16 415

I was going to question not using $F=fiend, but after testing it ends up being the same length to do so. – Kamil Drakari – 2017-10-23T15:47:59.663

@KamilDrakari Yeah, needs to be length of six or more because of the $ sigil :( – Dom Hastings – 2017-10-23T15:49:32.983

$} what a variable name ... – Titus – 2017-10-24T10:37:35.020

@Titus Yup! Almost anything works, although many have extra special meaning. I only used it there as if I'd used $W I'd have needed to use ${W} as it's next to another letter. – Dom Hastings – 2017-10-24T11:51:06.670

1I reckoned that. gotcha none the less :) – Titus – 2017-10-24T14:16:17.513

4

C# (Visual C# Compiler), 225 209 bytes

y=>c=>y<1818?"":y>1818?"frankenstein's monster":"wretch,monster,creature,demon,devil,it,fiend,vile insect,abhorred monster,wretched devil,abhorred devil".Split(',')[new System.Random().Next(c>9?6:0,c>9?11:7)];

Try it online!

-16 thanks to Kevin Cruijssen

Not particularly concise, but I would expect C# to take more space to declare and use any repeated strings the way the Python answer does than to just repeat them. The included test runner has a Thread.Sleep(1) inside the enumeration of test cases because default seeding for Random() uses the current time and the actual function runs fast enough to end up with the same seed on subsequent runs without a delay.

Calls to the func use currying syntax, f(year)(chapter) (or whatever name the function is stored in instead of f)

Kamil Drakari

Posted 2017-10-23T14:30:48.540

Reputation: 3 461

2I see you applied the same trick as I had in mind when I posted the challenge, putting fiend in the middle of a single string-array, since it's present in both lists. You can save some bytes by replacing new[]{"wretch","monster","creature","demon","devil","it","fiend","vile insect","abhorred monster","wretched devil","abhorred devil"} with "wretch,monster,creature,demon,devil,it,fiend,vile insect,abhorred monster,wretched devil,abhorred devil".Split(',') (-16 bytes) – Kevin Cruijssen – 2017-10-24T07:04:11.700

@KevinCruijssen Nice trick, It doesn't immediately seem beneficial but changing the delimiter from "," to just , makes up for the longer .Split(',') compared to new[]{} with more than a few items. – Kamil Drakari – 2017-10-24T14:10:54.647

3

Bash, 229, 206, 197, 179 bytes

m=monster
a=("Frankenstein's $m" wretch $m creature demon devil it fiend vile\ insect {abhorr,wretch}ed\ {devil,$m})
echo "${a[$1>1818?0:$1<1818?13:RANDOM%($2>9?5:7)+($2>9?7:1)]}"

the explanation about brace/variable expansions

m=monster
{abhorr,wretch}ed\ {devil,$m}

is first expanded to

abhorred\ {$m,devil} wretched\ {devil,$m}
abhorred\ $m abhorred\ devil wretched\ devil wretched\ $m

then variable m is expanded

abhorred\ monster abhorred\ devil wretched\ devil wretched\ monster

however following doesn't work because $w will be first joined with ed and wed is not defined and will be expanded to empty string.

m=monster
w=wretch
{abhorr,$w}ed\ {devil,$m}

it can be done adding explicit braces arround w but will be longer

m=monster
w=wretch
{abhorr,${w}}ed\ {devil,$m}

TIO

Nahuel Fouilleul

Posted 2017-10-23T14:30:48.540

Reputation: 5 582

You can save 4 bytes by creating variables for wretch and monster (225 bytes).

– Kevin Cruijssen – 2017-10-24T07:00:33.933

not so simple because of brace expansion which occurs before variable expansion – Nahuel Fouilleul – 2017-10-24T07:07:20.780

I (almost) never programmed in Bash, so could you clarify what you mean by that? It does seem to work in TIO, but maybe I'm missing something due to the way the programming language behaves.

– Kevin Cruijssen – 2017-10-24T07:09:59.113

printf '%s\n' "${b[@]}" after b=(..) will not give wretched devil for example – Nahuel Fouilleul – 2017-10-24T09:06:17.450

Ah ok, I get it now. It does seem to work with just m=monster, though. Try it here. Also, shouldn't d%5 be d%6 (the six options are fiend, vile insect, abhorred devil, abhorred monster, wretched devil, and wretched monster)?

– Kevin Cruijssen – 2017-10-24T09:18:05.287

in fact it is %5 because wretched monster was not specified in list but generated by cartesian product – Nahuel Fouilleul – 2017-10-24T09:27:29.820

1@KevinCruijssen thnak you i learnt something when braces are the last element expansion works – Nahuel Fouilleul – 2017-10-24T09:31:33.947

Making a variable for devil is actually longer than simply using it twice. :) v=devil $v$v = 12 bytes; devildevil = 10 bytes. – Kevin Cruijssen – 2017-10-24T09:46:20.017

I think you need to swap $m,devil to devil,$m because I think you're excluding wretched devil when you want to exclude wretched monster! :) – Dom Hastings – 2017-10-24T15:38:43.150

1@DomHastings, yes, fixed – Nahuel Fouilleul – 2017-10-25T07:25:22.770

2

Java (OpenJDK 8), 275 269 255 207 203 bytes

y->c->y<1818?0:y>1818?"Frankenstein's monster":"wretch;monster;creature;demon;devil;it;fiend;vile insect;abhorred monster;wretched devil;abhorred devil".split(";")[c+=Math.random()*(c>9?5:7)+(c>9?6:0)-c]

Try it online!

Roberto Graham

Posted 2017-10-23T14:30:48.540

Reputation: 1 305

1203 bytes. Use IntFunctions instead of Function<Integer> to get it working. – Olivier Grégoire – 2017-10-24T10:14:14.827

2

APL (Dyalog Unicode), 189 bytes

m←'monster'
a←'abhorred ',⊢
f←'fiend'
d←'devil'
{⊃⍵=1818:{⊃⌽⍵<10:(?7)⊃'wretch'm'creature' 'demon'd f'it'⋄(?5)⊃'vile insect'(a m)f('wretched ',⊢d)(a d)}⍵⋄{⊃⍵>1818:'frankenstein''s ',⊢m⋄''}⍵}

Try it online!

To test, just append the test case to the last curly bracket like so:

{⊃⍵=1818:{⊃⌽⍵<10:(?7)⊃'wretch'm'creature' 'demon'd f'it'⋄(?5)⊃'vile insect'(a m)f('wretched ',⊢d)(a d)}⍵⋄{⊃⍵>1818:'frankenstein''s ',⊢m⋄''}⍵}1818 10

Huge thanks to @ngn for helping out with the leading whitespace issue.

How it works:

It's worth noting that APL interprets strings as arrays (vectors) of characters, so 'wretch' 'creature' would be interpreted in other languages as [[w,r,e,t,c,h],[c,r,e,a,t,u,r,e]]

These are helper functions:

m←'monster'      #These are pretty self explanatory, variables m, f and d are being set to 'monster', 'fiend' and 'devil respectively.
f←'fiend'
d←'devil'
a←'abhorred ',⊢  # a is being set to 'abhorred ' concatenated with the argument to it's right.

This is the main function, which will be broken in 3 parts for better understanding:

{⊃⍵=1818:{⊃⌽⍵<10:(?7)⊃'wretch'm'creature' 'demon'd f'it'⋄(?5)⊃'vile insect'(a m)f('wretched ',⊢d)(a d)}⍵⋄{⊃⍵>1818:'frankenstein''s ',⊢m⋄''}⍵}

Part 1:

{⊃⍵=1818:{Part2}⍵⋄{Part3}⍵} # First conditional
        :                   # If
 ⊃                          # the first element
  ⍵                         # of the argument ⍵
   =1818                    # Equals the literal 1818
         {Part2}⍵           # Executes part 2 with argument ⍵
                 ⋄          # Else
                  {Part3}⍵  # Executes part 3 with argument ⍵

Part 2:

{⊃⌽⍵<10:(?7)⊃'wretch'm'creature' 'demon'd f'it'⋄ # Second conditional
(?5)⊃'vile insect'(a m)f('wretched ',⊢d)(a d)}⍵                
       :                                         # If
 ⊃                                               # the first element
  ⌽                                              # of the inverse
   ⍵                                             # of the argument ⍵
    <10                                          # is less than 10
           ⊃                                     # pick the nth
       (?7)                                      # random element between [1,7]
            'wretch'm'creature' 'demon'd f'it'   # from this string array
                                              ⋄  # Else
    ⊃                                            # pick the nth
(?5)                                             # random element between [1,5]
     'vile insect'(a m)f('wretched ',⊢d)(a d)    # from this string array
                                             }⍵  # using argument ⍵

Part 3:

{⊃⍵>1818:'frankenstein''s ',⊢m⋄''}⍵ # Third conditional
        :                           # If
 ⊃                                  # the first element
  ⍵                                 # of the argument ⍵
   >1818                            # is greater than 1818
         'frankenstein''s ',⊢m      # print the string "frankenstein's" concatenated with m (which prints monster)
                              ⋄     # else
                               ''   # print an empty string
                                 }⍵ # with argument ⍵

J. Sallé

Posted 2017-10-23T14:30:48.540

Reputation: 3 233

2

PHP, 184 176 bytes

<?=strtr([0,1,2,Creature,Demon,It,Fiend,30,31,"2ed 1","Vile Insect","Frankenstein´s 0"][[rand(6*$x=$argv[2]>9,6+4*$x),11][$argv[1]<=>1818]],[Monster,Devil,Wretch,"Abhorred "]);

Run with -n and give year and chapter as command line arguments or try it online.

index and thus result evaluate to NULL for year<1818, leading to empty output.

Titus

Posted 2017-10-23T14:30:48.540

Reputation: 13 814

What does $argv[1]<=>1818 do? I've never ever seen that. – Y U NO WORK – 2017-10-25T11:45:42.950

1

Javascript (ES6), 205 bytes

a="abhorred ",d="devil",f="fiend",m="monster"
y=>c=>y<1818?0:y>1818?"frankenstein's "+m:(l=c<10?[f,"wretch",m,"creature","demon",d,f,"it"]:["vile insect",a+m,f,"wretched "+d,a+d])[0|Math.random()*l.length]

Returns 0 if the year is less than 1818

a="abhorred ",d="devil",f="fiend",m="monster"
n=y=>c=>y<1818?0:y>1818?"frankenstein's "+m:(l=c<10?[f,"wretch",m,"creature","demon",d,f,"it"]:["vile insect",a+m,f,"wretched "+d,a+d])[0|Math.random()*l.length]
<div oninput="o.innerText=n(y.value)(c.value)"><input id=y type=number value=1817 /><input id=c type=number value=10 /></div><p id=o>0

Herman L

Posted 2017-10-23T14:30:48.540

Reputation: 3 611

1

C, 380 BYTES

void ok(int *year, int* chapter){char*below_10[] = {"wretch", "monster", "creature", "demon", "devil", "fiend", "it"}; char*at_10[] = {"vile insect", "abhorred monster", "fiend", "wretched devil", "abhorred devil"}; year < 1818?printf("0"):(year == 1818?(chapter<10 printf("%s",below_10[rand()%8]):printf("%s",at_10[rand()%7])):printf("Frankenstein's Monster"));}

Igbokwe Danny

Posted 2017-10-23T14:30:48.540

Reputation: 11

4

Hi, welcome to PPCG! In a code-golf challenge the goal is to have as few bytes as possible. So method/variable names are best as single characters. In addition, you can remove all unnecessary spaces and new-lines, and use the "Frankenstein's Monster" directly instead of making a variable for it. Also, where is the year and chapter coming from now? I don't see it as parameters of the method. Tips for golfing in <all languages> and Tips for golfing in C might be useful. Enjoy your stay! :)

– Kevin Cruijssen – 2017-10-24T11:37:29.250

No problem. And you can golf a bit more: void o(int y,int c){char*b[]={"wretch","monster","creature","demon","devil","fiend","it"},*a[]={"vile insect","abhorred monster","fiend","wretched devil","abhorred devil"};printf("%s",y<1818?0:y==1818?c>9?a[rand()%6]:b[rand()%7]:"Frankenstein's Monster");} 256 bytes Try it here! (I removed all unnecessary spaces, renamed method/variables/parameters to single letter; removed some unnecessary parenthesis at the ternary-if; single printf; changed <10 to >9; etc.) Not sure why rand() isn't working in TIO.. :S

– Kevin Cruijssen – 2017-10-25T07:25:01.227

234 bytes – ceilingcat – 2019-01-16T09:35:33.257

1

Javascript 199 bytes

M="monster"
A=(y,c)=>y<1818?"":y^1818?"Frankenstein's "+M:[W="wretch",M,"creature","demon",D="devil",F="fiend","it","vile insect",(H="abhorred ")+M,F,W+"ed "+F,H+D][Math.random()*(c>9?5:7)+7*(c>9)|0]

console.log(A(1700,1))
console.log(A(1700,12))
console.log(A(1817,10))
console.log(A(1818,1))
console.log(A(1818,9))
console.log(A(1818,10))
console.log(A(1818,11))
console.log(A(1819,1))
console.log(A(1819,18))
console.log(A(2017,24))

DanielIndie

Posted 2017-10-23T14:30:48.540

Reputation: 1 220

1

MBASIC, 288 bytes

1 DIM R$(12):FOR I=1 TO 12:READ R$(I):NEXT:INPUT Y,C:IF Y<1818 THEN 5
2 IF Y>1818 THEN O$="Frankenstein's Monster":GOTO 5
3 IF C>9 THEN O=7
4 O$=R$(O+INT(RND(1)*N+1))
5 PRINT O$:DATA wretch,monster,creature,demon,devil,fiend,it,vile insect,abhorred monster,fiend,wretched devil,abhorred devil

wooshinyobject

Posted 2017-10-23T14:30:48.540

Reputation: 171

0

05AB1E, 114 110 bytes

0…뢼–±¹.•ʒ¦Ë"ìËM₂G¶тá≠•ì#.•1ÏiT¥Ƶʒ“T¡Äg… 5ÀΘO¼™Ãí?ιË%4₄‡‡λYιi¾н••Jtm•17в£‚…'s 'ì³R7£R’¡¬ÿÿ±¹’¸¸)sŽ7X.S>èsT@èΩ

Outputs 0 when the year is below 1818.

Try it online or verify all test cases.

Explanation:

0                    # Push a 0
…뢼–±¹              # Push dictionary string "creature devil monster"
 .•ʒ¦Ë"ìËM₂G¶тá≠•   "# Push compressed string "demon fiend it wretch "
  ì                  # Prepend it: "demon fiend it wretch creature devil monster"
   #                 # Split by spaces: ["demon","fiend","it","wretch","creature","devil","monster"]
.•1ÏiT¥Ƶʒ“T¡Äg… 5ÀΘO¼™Ãí?ιË%4₄‡‡λYιi¾н•
                     # Push compressed string "abhorred devilabhorred monsterfiendvile insectwretched devil"
 •Jtm•               # Push compressed integer 1249548
      17в            # Converted to Base-17 as list: [14,16,5,11,14]
         £           # Split the string into parts of that size: ["abhorred devil","abhorred monster","fiend","vile insect","wretched devil"]
‚                    # Pair both string-lists together
…'s                 '# Push string "'s "
   'ì³              '# Push dictionary string "liechtenstein"
      R7£R           # Leave the last 7 characters: "enstein"
          ’¡¬ÿÿ±¹’   # Push dictionary string "frankÿÿmonster", where the "ÿ" are automatically
                     # replaced with the strings at the top of the stack: "frankenstein's monster"
                  ¸¸ # Wrap it twice into a list: [["frankenstein's monster"]]
)                    # Wrap everything on the stack into a list
                     # (We now have: [0,[["demon","fiend","it","wretch","creature","devil","monster"],["abhorred devil","abhorred monster","fiend","vile insect","wretched devil"]],[["frankenstein's monster"]]])
 s                   # Swap to get the first (implicit) input
  Ž7X                # Push compressed integer 1818
     .S              # Compare it with the input (-1 if below; 0 if equal; 1 if above)
       >             # Increase it by 1 (0 if below; 1 if equal; 2 if above)
        è            # Use it to index into the list
         s           # Swap to get the second (implicit) input
          T@         # Check if it's larger than or equal to 10 (results in 0 for falsey; 1 for truthy)
            è        # Use it to index into the inner list
             Ω       # And finally get a random value from that list (which is output implicitly)

See this 05AB1E tip of mine (sections How to use the dictionary?; How to compress strings not part of the dictionary?; How to compress large integers?; and How to compress integer lists?) to understand why:

  • …뢼–±¹ is "creature devil monster";
  • .•ʒ¦Ë"ìËM₂G¶тá≠• is "demon fiend it wretch ";
  • .•1ÏiT¥Ƶʒ“T¡Äg… 5ÀΘO¼™Ãí?ιË%4₄‡‡λYιi¾н• is "abhorred devilabhorred monsterfiendvile insectwretched devil";
  • •Jtm• is 1249548 and •Jtm•17в is [14,16,5,11,14];
  • 'ì³ is "liechtenstein ";
  • ’¡¬ÿÿ±¹’ is "frankÿÿmonster";
  • Ž7X is 1818.

Kevin Cruijssen

Posted 2017-10-23T14:30:48.540

Reputation: 67 575

-1

JavaScript, 194 B

e=Math.random,f=Math.floor;x=(a,b,c=`insect,monster,wretch,creature,demon,devil,fiend,it`.split`,`,d=[`vile `,`abhorred `])=>a<1818||a-1818?`Frankenstein's `+c[1]:(b<10||c[f(e()*2)])+c[f(e()*8)]

user75200

Posted 2017-10-23T14:30:48.540

Reputation: 141

doesnt really match the test cases – DanielIndie – 2017-10-24T18:12:56.310