# Help me redirecting

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!

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

# R, 98 bytes

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


Try it online!

• 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):// Apr 24 '18 at 16:58
• 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? Apr 24 '18 at 17:04
• 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 :( Apr 24 '18 at 17:06
• Damn, you're right. That'll learn me to read the instructions better. Fixed, and thanks for reigning me in =) Apr 24 '18 at 17:12
• 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 Apr 24 '18 at 17:15

m%://%||s%.*\.%http://$&%||s%^%ftp://%  Try it online! # Ruby, 6356 55 bytes ->a{a[%r*(https?|ftp)://*]?a:"#{a[?.]?'ht':?f}tp://"+a}  Try it online! • Erm your code just works if you supply the result in your code...? – 0x45 Apr 24 '18 at 11:05 • They were hardcoded tests, now it should be more dynamic – lfvt Apr 24 '18 at 11:11 # 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! • I managed to remove a few bytes: TIO May 3 '18 at 15:21 • @HermanL Wow, impressive! Thank you. May 3 '18 at 15:56 # 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. # 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>

• I think you have to use a regex; your current code fails for the a://b example. Apr 24 '18 at 16:52
• @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? Apr 24 '18 at 17:09
• I´d say it´d be fair to be precise, as all other submissions are so too: %^(ht|f)tps?://% should be ok though. Apr 24 '18 at 18:28

# 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
:                 //   Else:
+"tp://"+s         //   And append "tp://" and the input-String

• -2 bytes using s->s.matches("(https?|ftp)://.*")?s:(s.contains(".")?"ht":"f")+"tp://"+s Apr 24 '18 at 12:04
• @HermanLauenstein Pretty obvious change now that I see it, but I hadn't thought of it at all, so thanks! :) Apr 24 '18 at 12:09

# Retina, 64 bytes

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


Try it online!

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

• 'htt':'ft'}p -> 'ht':'f'}tp
– tsh
Apr 24 '18 at 2:24
• Won't this fail for abcd://site? Expected output is ftp://abcd://site. Apr 24 '18 at 7:48
• @Shaggy That's why I say "Real life assumption". In comment such are invalid input
– l4m2
Apr 24 '18 at 8:49
• 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. Apr 24 '18 at 15:19

# 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


# 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

• Maybe re.match(r'://',s) should be enough
– tsh
Apr 24 '18 at 2:23
• @tsh: It´s not. Look at the latest test case. But I´d personally say that ^(ht|f)tps?:// should be ok. Apr 24 '18 at 18:28
• 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) Apr 25 '18 at 11:03

# Pyth, 58 bytesSBCS

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


Test suite