5
\$\begingroup\$

Your task is to automatically complete URLs like the address bar in most browsers is doing. We will use the following (simplified) rules:

  • If the input string starts with http://, ftp:// or https://, return the string unchanged.
  • Otherwise, if the input string contains a dot ., e.g. in.put then the HTTP is assumed and http:// is prepended: http://in.put.
  • Otherwise ftp:// is prepended, e.g. ftp://input when the input string was input.

Input

Any string which must not necessarily be a valid URL.

Output

The string modified according to the above rules.

Test Cases

dan-pc -> ftp://dan-pc
https://localhost/ -> https://localhost/
ftp://foo -> ftp://foo
http://foo -> http://foo
f.oo -> http://f.oo
derp.me -> http://derp.me
another.one/ ->http://another.one/
// -> ftp://// 
a://b -> ftp://a://b

This is code golf, shortest code wins. Good Luck!

\$\endgroup\$
16
  • 2
    \$\begingroup\$ Can the input be abcd://site? (generally if there is something before :// can we assume it's http, https or ftp? \$\endgroup\$
    – DELETE_ME
    Apr 24, 2018 at 0:14
  • \$\begingroup\$ nope. You do not have to take care of "invalid" input. Yes , your assumption is right @user202729 \$\endgroup\$
    – 0x45
    Apr 24, 2018 at 0:18
  • 2
    \$\begingroup\$ Then which inputs are valid? \$\endgroup\$
    – DELETE_ME
    Apr 24, 2018 at 0:18
  • 3
    \$\begingroup\$ I'd suggest adding a test case for http://foo \$\endgroup\$
    – Chas Brown
    Apr 24, 2018 at 0:42
  • 1
    \$\begingroup\$ Can the input be an arbitrary string? It looks like answers are assuming it's formatted like a URL. \$\endgroup\$
    – xnor
    Apr 24, 2018 at 2:31

12 Answers 12

3
\$\begingroup\$

R, 98 bytes

x=scan()
cat(`if`(grepl("^(https?|ftp)://",x),"",`if`(grepl("\\.",x),"http://","ftp://")),x,sep="")

Try it online!

\$\endgroup\$
5
  • \$\begingroup\$ This won't quite work, for a couple of reasons: the regex . in the second grepl matches any single character, you need \\. instead. Additionally, the first grepl will match anything that has p:// or s:// as a substring; you need to use a regex like others have used, ^(https?|ftp):// \$\endgroup\$
    – Giuseppe
    Apr 24, 2018 at 16:58
  • \$\begingroup\$ Whoops, you're right about the latter grepl, fixed that. But the first one correctly matches all the test cases as they currently stand, I can update this if need be. Or is that considered bad form? \$\endgroup\$ Apr 24, 2018 at 17:04
  • \$\begingroup\$ The input is specified as Any string which must not necessarily be a valid URL. so I think you need that update. Which is annoying, to be sure. String challenges in R are seldom fun :( \$\endgroup\$
    – Giuseppe
    Apr 24, 2018 at 17:06
  • \$\begingroup\$ Damn, you're right. That'll learn me to read the instructions better. Fixed, and thanks for reigning me in =) \$\endgroup\$ Apr 24, 2018 at 17:12
  • \$\begingroup\$ not a problem, I've been burned so many times before...I must have ten or so answers I deleted for not meeting the specs that I never went back to. =P \$\endgroup\$
    – Giuseppe
    Apr 24, 2018 at 17:15
2
\$\begingroup\$

Perl 5 -p, 38 bytes

m%://%||s%.*\.%http://$&%||s%^%ftp://%

Try it online!

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

Ruby, 63 56 55 bytes

->a{a[%r*(https?|ftp)://*]?a:"#{a[?.]?'ht':?f}tp://"+a}

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Erm your code just works if you supply the result in your code...? \$\endgroup\$
    – 0x45
    Apr 24, 2018 at 11:05
  • 2
    \$\begingroup\$ They were hardcoded tests, now it should be more dynamic \$\endgroup\$
    – lfvt
    Apr 24, 2018 at 11:11
2
\$\begingroup\$

Swift, 147 133 bytes

Thanks to Herman L for saving 14 bytes.

Sadly, NSRegularExpression would've taken away lots of precious bytes.

import Foundation;let s=readLine()!,h=["http://","https://","ftp://"];print(h.contains{s.hasPrefix($0)} ?s:h[s.contains(".") ?0:2]+s)

Prettyfied:

import Foundation

let s = readLine()!, h = ["http://","https://","ftp://"]
print(h.contains{ s.hasPrefix($0) } ? s :h[s.contains(".") ? 0 : 2] + s)

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I managed to remove a few bytes: TIO \$\endgroup\$
    – Endenite
    May 3, 2018 at 15:21
  • \$\begingroup\$ @HermanL Wow, impressive! Thank you. \$\endgroup\$ May 3, 2018 at 15:56
1
\$\begingroup\$

JavaScript (Firefox 52), 41 bytes

s=>new URL(s,/\./.test(s)?'http:':'ftp:')

If a string is required for output, add 3 bytes +'' at the end. (Notice this solution may add a trailing / at the end of domain name since they are the same URL)

f=
s=>new URL(s,/\./.test(s)?'http:':'ftp:')

t=s=>console.log(`${s} -> ${f(s)}`)

t('example.com')
t('example')
t('http://example')
t('https://example')
t('ftp://example')
t('http://example.com')
t('https://example.com')
t('ftp://example.com')

It seems this only works on Firefox 52 ESR but not Firefox 60 or Chrome 65. So sad.

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

PHP, 59 bytes

<?=strpos($s=$argn,':')?$s:(strpos($s,'.')?ht:f)."tp://$s";

To run all the tests:

cat <<EOF | php -nF <filename>
dan-pc
https://localhost/
ftp://foo
http://foo
f.oo
derp.me
another.one/
EOF

(Put a newline before the <?= for formatting, not required for one line of input)

Or just one at a time:

echo '<input>' | php -nF <filename>

Or Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ I think you have to use a regex; your current code fails for the a://b example. \$\endgroup\$
    – Titus
    Apr 24, 2018 at 16:52
  • \$\begingroup\$ @Titus Oh, I didn't see that new test case. Thanks for letting me know. Do you think it'd be acceptable to just do 'p:' instead of ':', since it fulfills the test cases, or would it be more "right" to use a regex? \$\endgroup\$
    – Ethan
    Apr 24, 2018 at 17:09
  • \$\begingroup\$ I´d say it´d be fair to be precise, as all other submissions are so too: %^(ht|f)tps?://% should be ok though. \$\endgroup\$
    – Titus
    Apr 24, 2018 at 18:28
1
\$\begingroup\$

Java 8, 74 72 bytes

s->s.matches("(https?|ftp)://.*")?s:(s.contains(".")?"ht":"f")+"tp://"+s

-2 bytes thanks to @HermanLauenstein.

Try it online.

Explanation:

s->                   // Method with String as both parameter and return-type
  s.matches("(https?|ftp)://.*")?
                      //  If the input starts with one of
                      //  "http://", "https://", or "ftp://"
   s                  //   Return it as is
  :                   //  Else:
   (s.contains(".")?  //   If it contains a dot
     "ht"             //    Start with "ht"
    :                 //   Else:
     "f")             //    Start with "f"
   +"tp://"+s         //   And append "tp://" and the input-String
\$\endgroup\$
2
  • 1
    \$\begingroup\$ -2 bytes using s->s.matches("(https?|ftp)://.*")?s:(s.contains(".")?"ht":"f")+"tp://"+s \$\endgroup\$
    – Endenite
    Apr 24, 2018 at 12:04
  • \$\begingroup\$ @HermanLauenstein Pretty obvious change now that I see it, but I hadn't thought of it at all, so thanks! :) \$\endgroup\$ Apr 24, 2018 at 12:09
1
\$\begingroup\$

Retina, 64 bytes

^(?!(https?|ftp)://)(?=.*\.)
http://
^(?!(https?|ftp)://)
ftp:// 

Try it online!

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

JavaScript, 64 bytes

x=>x.match`^(https?|ftp)://`?x:`${/\./.test(x)?'ht':'f'}tp://`+x

JavaScript, 51 50 bytes, Real life assumption

x=>x.match`//`?x:`${/\./.test(x)?'ht':'f'}tp://`+x

Thank tsh for 1 byte

\$\endgroup\$
4
  • \$\begingroup\$ 'htt':'ft'}p -> 'ht':'f'}tp \$\endgroup\$
    – tsh
    Apr 24, 2018 at 2:24
  • \$\begingroup\$ Won't this fail for abcd://site? Expected output is ftp://abcd://site. \$\endgroup\$
    – Shaggy
    Apr 24, 2018 at 7:48
  • \$\begingroup\$ @Shaggy That's why I say "Real life assumption". In comment such are invalid input \$\endgroup\$
    – l4m2
    Apr 24, 2018 at 8:49
  • \$\begingroup\$ No, the comments were clarifying that those inputs were valid but inputs with an invalid protocol should be treated the same as inputs with no protocol. The test cases have been updated to reflect this. \$\endgroup\$
    – Shaggy
    Apr 24, 2018 at 15:19
1
\$\begingroup\$

GolfScript, 58 55 bytes

.'://':a/.,(\0=['https'.4<'ftp']:l?)*{}{.'.'?)!)l=a@}if

Try it online!

This is my first GolfScript program, so I expect there is a lot room for golfing.

Explanation:

.'://':a/.,(\0=['https'.4<'ftp']:l?)*{}{.'.'?)!)l=a@}if Full program, implicit input
.                                                       Copy input
 '://':a                                                Push '://', and assign it to a
        /.                                              Split input at '://' and copy
          ,(                                            Push length of the result - 1 (<==> '://' in input)
            \0=                                         Pull up the array and get the first element
               ['https'.4<'ftp']:l                      Push [ 'https', 'http', 'ftp' ] and assign it to l
                                  ?)                    Test if first element is in that array
                                    *{}{            }if If at least one of those values is false
                                        .'.'?)          Push whether the input contains a dot
                                              !)        Logical not and increment:
                                                              '.' in input -> 1
                                                           no '.' in input -> 2
                                                l=      Get that element of l ([ 'https', 'http', 'ftp' ])
                                                  a@    Append a ('://') and input
                                                        Implicit output
\$\endgroup\$
1
\$\begingroup\$

Python 2, 87 85 bytes

lambda s:re.match('(https?|ftp)://',s)and s or['f','ht']['.'in s]+'tp://'+s
import re

Try it online!

-2 bytes thx to Titus and wastl

\$\endgroup\$
3
  • \$\begingroup\$ Maybe re.match(r'://',s) should be enough \$\endgroup\$
    – tsh
    Apr 24, 2018 at 2:23
  • \$\begingroup\$ @tsh: It´s not. Look at the latest test case. But I´d personally say that ^(ht|f)tps?:// should be ok. \$\endgroup\$
    – Titus
    Apr 24, 2018 at 18:28
  • \$\begingroup\$ I don't think ftps is considered a valid protocol. But you can save two bytes by removing r and ^ (re.match does only apply the regex at the beginning) \$\endgroup\$
    – wastl
    Apr 25, 2018 at 11:03
1
\$\begingroup\$

Pyth, 58 bytesSBCS

J"://"I:Q."(|e<UGÐÌ@ãy!'"ZQ.?I}\.Q++"http"JQ.?++"ftp"J

Test suite

Code contains unprintable characters, and as such does not display properly on Stack Exchange. The link provided contains these characters and is the correct version of the program.

\$\endgroup\$

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.