8
\$\begingroup\$

Story

I need to remember a lot of passwords and don't want to use the same one for multiple websites so I came up with a rule, but the rule shouldn't be transparent so what I do is:

  • Think of a long word or concept such as breadpudding.
  • Replace the first letter with the site we are logging into. If we are logging into google, our word becomes greadpudding.
  • Make the first letter uppercase.
  • Change the second letter to an @ sign.
  • If the password starts with a non-consonant, add a certain number (such as 1234); otherwise, add another number (such as 4321).

Ta da, you now have an adequate password.

This process is arduous though so I need a program to generate this for me based on the following:

Problem

Given input:

  • a : the initial word, which is a string and is always lowercase, and is guaranteed to be longer than 3 characters.
  • b : the site we are logging into, which is a string and is always lowercase, and is guaranteed to be non-empty.
  • c : the number for non-consonants, which is a positive integer that may have leading zeroes.
  • d : the number for consonants, which is a positive integer that may have leading zeroes.

Output a string based on above criteria.

Test cases

Input a="volvo", b="gmail", c=5555, d="0001"

G@lvo0001

Input a="sherlock", b="9gag", c=31415926535, d=3

9@erlock31415926535

Input a="flourishing", b="+google", c=11111, d=2222

+@ourishing11111

Rules

  • y is a consonant.
  • If you decide c or d is an integer, you may parse it as such, and leading zeroes can be ignored (0091 gets treated as 91).
  • Trailing whitespace and newlines are allowed.
  • You may output the result to STDOUT or return the result in a function.
  • Characters allowed in a and b are [a-z0-9!@#$%^&*()_+=-].
  • You may accept the 4 inputs in any consistent order.

This is . Shortest code in bytes wins.

\$\endgroup\$
  • 5
    \$\begingroup\$ Through 20 years of effort, we've successfully trained everyone to use passwords that are hard for humans to remember, but easy for computers to guess. Strength of password is never determined by how many uppercase/special characters there is in the password. \$\endgroup\$ – Leaky Nun Jun 21 '17 at 7:33
  • \$\begingroup\$ @LeakyNun Yes I agree but the amount of character sets allowed makes it harder as well, so imagine if a password box only allowed lowercase letters, that decreases the difficulty of brute-forcing a lot. \$\endgroup\$ – LiefdeWen Jun 21 '17 at 7:36
  • \$\begingroup\$ Yes, at a given length inclusion of more types of characters (numbers, uppercase, symbols) increases security, but not exponentially. A long all lowercase letter password is much stronger than a short mixed character type password. According to zxcvbn: "4321breadpudding" (10^9) broken in <1s stored as fast hash, "4321G@eadpudding" (10^11) broken in 8s, "granny makes great bread pudding" (10^24) broken in centuries, "Granny, make great bread pudding!" (10^27) broken in centuries. Remember to calculate password difficulty in orders of magnitude, in which case 2 is not a lot! \$\endgroup\$ – vee_ess Jun 21 '17 at 10:56
  • 3
    \$\begingroup\$ "How long does G@anny makes great bread pudding1234 take to get broken"? Well, now it's on all the crackz0rd lists so less than 1 second :-P \$\endgroup\$ – Olivier Grégoire Jun 21 '17 at 13:02
  • 1
    \$\begingroup\$ @LeakyNun Did you read the flavor text for that xkcd comic..? \$\endgroup\$ – Poke Jun 21 '17 at 13:25

16 Answers 16

2
\$\begingroup\$

Jelly, 17 bytes

Ḣ©Œu;”@o;⁶⁵®eØC¤?

A full program, taking the arguments in the order b, a, c, d.

Try it online!

How?

The main link is dyadic, taking b and a, the program inputs are then b, a, c, and d (the 3rd through sixth command line arguments), so c and d are accessed as such.

Ḣ©Œu;”@o;⁶⁵®eØC¤?  Main link: b, a           e.g. "gmail", "volvo" (c="5555" and d="0001")
Ḣ                  head b                         'g'
 ©                 copy to register and yield     'g'
  Œu               convert to uppercase           "G"
     ”@            literal '@' character          '@'
    ;              concatenate                    "G@"
       o           logical or with a (vectorises) "G@lvo"
                ?  if:
               ¤     nilad followed by link(s) as a nilad:
           ®           recall value from register  'g'
             ØC        yield consonants            "BCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz"
            e          exists in?                  1
         ⁶         ...then: 6th arg = 4th in = d   "0001" 
          ⁵        ...else: 5th arg = 3rd in = c   "5555"
        ;          concatenate                     "G@lvo0001"
                   implicit print
\$\endgroup\$
3
\$\begingroup\$

Python 3, 69 bytes

lambda a,b,*c:b[0].upper()+"@"+a[2:]+c[b[0]in"bcdfghjklmnpqrstvwxyz"]

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Why not use b[0]not in"aeiou" instead? \$\endgroup\$ – officialaimm Jun 21 '17 at 8:43
  • 3
    \$\begingroup\$ @officialaimm because for some godforsaken reason 9 is counted as a non-consonant. \$\endgroup\$ – Leaky Nun Jun 21 '17 at 8:45
  • \$\begingroup\$ Yea, the rule in the question does not say anything about the numbers explicitly... \$\endgroup\$ – officialaimm Jun 21 '17 at 8:48
  • 2
    \$\begingroup\$ Save 3 bytes (note: z is the maximum char possible): ('a'<b[0])*b[0]not in"eiou" \$\endgroup\$ – Jonathan Allan Jun 21 '17 at 8:57
2
\$\begingroup\$

05AB1E, 22 20 18 bytes

н©u'@I¦¦žN®åiI\}IJ

Input taken as b,a,c,d

Try it online!

Explanation (outdated)

¦                     # remove the first char of a
 s                    # swap b to the top of the stack
  н©                  # push the head of b and store a copy in register
    uì                # convert the head to upper case and prepend to a
      U               # store in variable X
       žN®åi          # if the head of b is a consonant
            \}        # discard c
              X«      # concatenate X with c or d
                '@1ǝ  # insert an "@" at character position 1

used in the link as н isn't pulled to TIO yet.

\$\endgroup\$
2
\$\begingroup\$

Javascript ES6, 87 bytes

(a,b,c,d)=>b[0].toUpperCase()+'@'+a.slice(2)+(/[bcdfghjklmnpqrstvwxyz]/.test(b[0])?d:c)

Demo

f=
(a,b,c,d)=>b[0].toUpperCase()+'@'+a.slice(2)+(/[bcdfghjklmnpqrstvwxyz]/.test(b[0])?d:c)

console.log(f("volvo","gmail", 5555, "0001")); //G@lvo0001
console.log(f("sherlock","9gag", 31415926535, 3)); //9@erlock31415926535
console.log(f("flourishing","+google", 11111, "2222")); //+@ourishing11111

\$\endgroup\$
  • \$\begingroup\$ I was about to post this. I mean, literally this, character by character. Bummer, lol \$\endgroup\$ – Hankrecords Jun 21 '17 at 14:28
  • \$\begingroup\$ @Hankrecords Hehe, we can maybe improve it \$\endgroup\$ – Weedoze Jun 22 '17 at 6:07
  • \$\begingroup\$ Since {|}~ are not valid characters, you can replace /[bcdfghjklmnpqrstvwxyz]/.test(b[0])?d:c with /[ -_aeiou]/.test(b[0])?c:d for minus 13 bytes \$\endgroup\$ – PunPun1000 Jun 22 '17 at 13:12
2
\$\begingroup\$

C, 441 286 139 Bytes

#define o(c)*a[1]==0xc
int main(int b,char** a){printf("%c@%s%s",*a[1],a[2]+2,(*a[1]>97&*a[1]<128)
&!(o(65)|o(69)|o(6F)|o(75))?a[4]:a[3]);}
\$\endgroup\$
  • 1
    \$\begingroup\$ erm... instead of 21 sets of argv[1][0]='c'|argv[1][0]='c'|... where c = consonant, you can easilly reduce this by doing !(argv[1][0]='a'|argv[1][0]='e'|argv[1][0]='i'|argv[1][0]='o'|argv[1][0]='u') Reduces score by 264 just by that! \$\endgroup\$ – Baldrickk Jun 21 '17 at 10:50
  • \$\begingroup\$ No, as mentioned otherwise, that allows numbers and other characters \$\endgroup\$ – Blue Jun 21 '17 at 11:15
  • \$\begingroup\$ @muddyfish then you make it (argv[0][1]>='a'&argv[0][1]<='z'&!(argv[1][0]='a'|argv[1][0]='e'|argv[1][0]='i'|argv[1][0]='o‌​'|argv[1][0]='u')). Still shorter by a margin. However there are so many ways to golf this code I don't know where to start... :s \$\endgroup\$ – Olivier Grégoire Jun 21 '17 at 13:22
  • \$\begingroup\$ I am open to ideas :) This is my first attempt at golfing \$\endgroup\$ – ulascan Jun 21 '17 at 16:11
  • \$\begingroup\$ Well, you're doing fine! I'm sure it can still be improved, like using a variable instead of using a macro, but yeah, you're starting on the right foot! :) You could probably make good use of these golfing tips! \$\endgroup\$ – Olivier Grégoire Jun 21 '17 at 18:57
2
\$\begingroup\$

R, 105 103 bytes

pryr::f({m=substr(b,0,1);paste0(toupper(m),'@',substring(a,3),'if'(grepl("[b-df-hj-np-tv-z]",m),d,c))})

Anonymous function. Evaluates to

function (a, b, c, d) 
{
    m = substr(b, 0, 1)                      #first letter of website
    paste0(toupper(m),                       #concatenate that letter, capitalized,
           "@",                              #an '@',     
           substring(a, 3),                  #the rest of the long string,
           if(                               #and
           grepl("[b-df-hj-np-tv-z]", m)),   #if the first letter is a consonant,
           d                                 #the consonant string/num,
           else c)                           #else the other one
}

which is what's on TIO. Please help me golf that regex because I'm terrible at them.

Saved 2 bytes from Giuseppe.

Try it online!

\$\endgroup\$
  • \$\begingroup\$ you could use !grepl('[aeiouy]',m) \$\endgroup\$ – Giuseppe Jun 21 '17 at 15:20
  • 1
    \$\begingroup\$ or better yet, grepl('[aeiouy]',m) and just swap c and d. \$\endgroup\$ – Giuseppe Jun 21 '17 at 15:22
  • \$\begingroup\$ 93 bytes "if" makes the if syntax much neater instead of using else or ifelse; I also saved substring to a variable and put m to uppercase immediately to save a byte. \$\endgroup\$ – Giuseppe Jun 21 '17 at 15:31
  • 1
    \$\begingroup\$ I tried running your function and ran into two issues: pryr is trying to make substring an argument; and your grepl only finds "not vowels", which isn't the same as consonants. The "if" thing I just missed, thanks for pointing that out. \$\endgroup\$ – BLT Jun 21 '17 at 17:15
  • \$\begingroup\$ I hadn't actually tested it; I didn't realize pryr::f wouldn't like that; you could use the regex '[a-z&&[^aeiouy]]' from Kevin Cruijissen's answer? \$\endgroup\$ – Giuseppe Jun 21 '17 at 17:46
2
\$\begingroup\$

Retina, 80 75 bytes

^..(.*)¶(.).*
$2@$1
^([ -_aeiou].*)¶(.*)¶.*
$1$2
(.*)¶.*¶(.*)
$1$2
T`l`L`^.

Try it online!

Trying out a new language here, takes inputs in the order given in the question

Explanation:

^..(.*)¶(.).*
$2@$1

Create a word which is second word first letter, @ sign, first word from the 3rd character on.

^([ -_aeiou].*)¶(.*)¶.*
$1$2

If the word starts with a non-consonant, append the first number

(.*)¶.*¶(.*)
$1$2

If there are still 3 lines left (no substitution in the last step, so it starts with a consonant), append the second number

T`l`L`^.

Uppercase the first letter

\$\endgroup\$
1
\$\begingroup\$

QBIC, 81 bytes

G=ucase$(_s;,1|)+@@`+_s;,3,_lC||~instr(@bcdfghjklmnpqrstvwxyz`,_sC,1|)|?G+;\?G+;

Explanation

Parameters are Website(A$), base word(C$), consonant-number(E$), and nonsonant-number(F$)
G=                           SET G$ to
 ucase$(      )              the upper-case version of (also works for '9gag', '+google')
        _s;,1|                  the first char of the website A$ read from cmd line
 +@@`                        plus a literal @ (B$)
 +_s;,3,_lC||                plus all characters from base word C$ from 3rd char onwards
~instr(                      IF the second arg to INSTR is in the first
 @bcdfghjklmnpqrstvwxyz`,      with all consonants in the first arg
 _sC,1|                        and the first char of the base word C$ in the second
 )
|?G+;                        THEN print G$ plus the consonant addition
\?G+;                        ELSE print G$ plus the other addition

Note that the last two lines appear the same, but the interpreter changes the behaviour slightly on each ;: Whenever it sees the ; instruction, it creates a new variable (in this case, the vars È$andF$` are the first available after reading all other literals and cmd line arguments) and assigns the first not-yet-assigned cmd line paraeter to that variable.

\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 76 bytes

(a,b,c,d)=>b[0].toUpperCase()+'@'+a.slice(2)+(/[aeiou\d_\W]/.test(b[0])?c:d)

I would have added this as a suggestion as an improvement to Weedoze's solution, but it seems like I can't comment on it since I mostly lurk

\$\endgroup\$
1
\$\begingroup\$

C#, 111 bytes

(a,b,c,d)=>Char.ToUpper(b[0])+"@"+a.Substring(2)+(b.IndexOfAny("bcdfghjklmnpqrstvwxyz".ToCharArray()==0)?d:c);

Checking the consonant is particularly expensive with no direct regex capability on the string type.

\$\endgroup\$
1
\$\begingroup\$

F#, 157 bytes

let f(a:string)(b:string)c d=System.Char.ToUpper(b.[0]).ToString()+"@"+a.[2..]+(if((Seq.except['e';'i';'o';'u']['b'..'z'])|>Seq.contains b.[0])then d else c)

F# is still very new to me so there are probably better approaches to this.

\$\endgroup\$
1
\$\begingroup\$

Java 8, 112 99 92 87 bytes

(a,b,c,d)->b.toUpperCase().charAt(0)+"@"+a.substring(2)+(b.matches("[a-z&&[^aeiou]].*")?d:c)

-13 bytes by taking parameter b last instead of second.
-1 byte by removing y
-7 bytes thanks to @OlivierGrégoire (and parameters are in order again)
-5 bytes thanks to @PunPun1000

Explanation:

Try it here.

(a,b,c,d)->                     // Method with 4 String parameters and String return-type
  b.toUpperCase().charAt(0)     //  First character of B capitalized
  +"@"                          //  + literal "@"
  +a.substring(2)               //  + A excluding first two characters
  +(b.matches("[ -_aeiou].*")?  //  If B starts with a consonant:
    d                           //   + D
   :                            //  Else:
    c)                          //   + C
                                // End of method (implicit / lambda with single return)
\$\endgroup\$
  • 1
    \$\begingroup\$ y is a consonant so you can drop the y in your regex for 1 byte. \$\endgroup\$ – LiefdeWen Jun 21 '17 at 10:19
  • 2
    \$\begingroup\$ (a,b,c,d)-> is shorter than a->b->c->d->. Currying is only helpful for 2 parameters. For 3, currying is the same as no currying. For 4 and above, no currying is shorter. \$\endgroup\$ – Olivier Grégoire Jun 21 '17 at 12:49
  • 1
    \$\begingroup\$ (a,b,c,d)->b.toUpperCase().charAt(0)+"@"+a.substring(2)+(b.matches("[a-z&&[^aeiou]].*")?d:c) is 92 bytes long. Also, it uses the parameters in proper order (which confused me at first :-( ). \$\endgroup\$ – Olivier Grégoire Jun 21 '17 at 13:09
  • 1
    \$\begingroup\$ @OlivierGrégoire Thanks. Second time I make that mistake regarding the currying with four parameters.. And first toUpperCase() and then .charAt(0) is indeed shorter.. Not sure how I've missed that. (And the different order was to allow (b=...), which wouldn't be possible if it isn't the last parameter with currying, because then it had to be final / was implicit final.) \$\endgroup\$ – Kevin Cruijssen Jun 21 '17 at 18:58
  • 1
    \$\begingroup\$ Since {|}~ are not valid characters, you can use [ -_aeiou] for non consonants and swap d and c for minus 5 bytes \$\endgroup\$ – PunPun1000 Jun 22 '17 at 12:34
0
\$\begingroup\$

V, 25 bytes

ldvjr@Ç^[aeiou]ü^Á/j

DÍî

Try it online!

Takes arguments in the buffer in order:

website
word/phrase
consonant number
non-consonant number
\$\endgroup\$
0
\$\begingroup\$

Bash 4, 76 bytes

g(){
a=${2:0:1}
c=$4
[[ "aeiou[0-9]" =~ .*$a.* ]]&&c=$3
p="${a^}@${1:2}$c"
}

Works in Bash 4:

g volvo gmail 5555 0001; echo $p
g sherlock 9gag 31415926535 3; echo $p
g flourishing +google 11111 2222; echo $p
\$\endgroup\$
0
\$\begingroup\$

Ruby, 73 bytes

->a,b,c,d{a.sub(/..(.*)/){b[0].upcase+"@#$1#{b[0]=~/[aeiou_\d\W]/?c:d}"}}

Try it online!

\$\endgroup\$
0
\$\begingroup\$

JavaScript (ES6), 69 bytes

(a,b,c,d)=>e=a[0].toUpperCase()+"@"+a.slice(2)+/[AEIOU]/.test(e)?c:d

Pretty simple, probably can be golfed

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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