16
\$\begingroup\$

Your task is to create a program which, given an input string, will output the first Google autocomplete result for that search. The format of input/output is up to you.

Rules

  1. Your program must take 1 input, a string, and output the top Google autocomplete/auto-fill suggestions result. The format of input/output is up to you. Just be sure to mention what your I/O format is.
  2. Obviously, accessing the Internet is allowed.
  3. URL shorteners (like bit.ly, TinyURL, etc.) are strictly disallowed. You should fetch your autocomplete results from this URL: http://suggestqueries.google.com/complete/search?client=your_browser&q=your_query or http://google.com/complete/search?client=your_browser&q=your_query. You are allowed to assume any browser name (or string, for that matter) for client. In the program I wrote, I assume Chrome. Any browser name or string should work. You are allowed to pass any options to the webpage as long as you are using some variant of http://suggestqueries.google.com/complete/search.
  4. Please provide an explanation of how your program works. It is not mandatory, but I strongly advise it.
  5. All standard loopholes are strictly forbidden.

Test Cases

These are constantly changing, so edit this post if these become out-of-date.

'how to'
  => 'how to make slime'
'code golf'
  => 'code golf languages'
'you'
  => 'youtube'
'g'
  => 'google' (why would you google 'google'?)

This is , so may the shortest code win and the best programmer prosper...

\$\endgroup\$
  • 3
    \$\begingroup\$ I would standardise a client name, to make it fair \$\endgroup\$ – Beta Decay Apr 23 '17 at 21:16
  • 7
    \$\begingroup\$ Why the strict URL? As long as suggestqueries.google.com is used, without any URL shorteners, I don't see any problems. \$\endgroup\$ – Dennis Apr 23 '17 at 21:30
  • \$\begingroup\$ In particular, if we can use output=toolbar, we don't have to specify a client at all. \$\endgroup\$ – Dennis Apr 23 '17 at 21:36
  • 2
    \$\begingroup\$ @mınxomaτ but why not https -> http (save 1 byte), remove www. (save 4 bytes), google.com -> google.us (save 1 byte) or even google.com -> g.cn (save 6 bytes; i'm not sure why this still works, but it seems that it still working in 20170424) \$\endgroup\$ – tsh Apr 24 '17 at 1:23
  • 3
    \$\begingroup\$ Aren't search suggestions different for different users and regions? I don't think having standard test cases really works for this. \$\endgroup\$ – MrZander Apr 24 '17 at 15:53
8
\$\begingroup\$

Zsh + coreutils + w3m, 88 71 68 bytes

echo `w3m "google.com/complete/search?client=gma&q=$*"|cut -d\" -f4`

Switching from Bash to Zsh saved 3 bytes.

Thanks to @FatalMerlin for the shorter URL, saving 17 bytes!

Sample run

$ zsh complete.sh how to
how to make slime
$ zsh complete.sh dont you
don't you forget about me
$ zsh complete.sh don\'t you
don't you worry child
\$\endgroup\$
  • 3
    \$\begingroup\$ Of all things, why is "make slime" the first suggestion? Just how many people are out there making slime as we speak? \$\endgroup\$ – MildlyMilquetoast Apr 23 '17 at 23:55
  • 27
    \$\begingroup\$ No clue. It was how to raise your i.q. by eating gifted children for a while, so I'd consider this an improvement. \$\endgroup\$ – Dennis Apr 23 '17 at 23:57
  • \$\begingroup\$ Dang, I do love w3m. It lets me browse without distractions and it's just pretty cool altogether. \$\endgroup\$ – ckjbgames Apr 24 '17 at 0:21
  • 1
    \$\begingroup\$ @MistahFiggins Blame Minecraft for that one. \$\endgroup\$ – JakeSteam Apr 24 '17 at 11:27
  • \$\begingroup\$ @MistahFiggins Maybe they all just want to make(1) slime. \$\endgroup\$ – Arminius Apr 24 '17 at 15:17
12
\$\begingroup\$

Vim 8 + unimpaired.vim, 93 89 85 70 73 71 bytes

  • -4 bytes thanks to tsh
  • -2 bytes thanks to Ian Emnace
  • -2 bytes thanks to FatalMerlin
  • -1 byte thanks to tsh/ckjbgames
:s/ /+/g
D:e http://google.us/complete/search?client=gma&q="
d3f";D]yy

As a bonus, the last bytes look like they're winking at you ;D Since this contains non-printing characters, the explanation contains substitutions (and I've replaced the pre-querystring part of the url with [url], for brevity):

:s/ /+/g<CR>D:e [url]?client=gma&q=<C-R>"<CR>d3f";D]yy
:s/ /+/g<CR>                                           " Replace spaces with +
            D                                          " Delete and yank result
             :e                                        " Type :e ('edit' command) and a space
                [url]?client=gma&q=                    " Type the url, except the query
                                   <C-R>"              " Paste from the default register
                                         <CR>          " Execute the command, which opens the response
                                                       "   in a new buffer
                                             d3f"      " Delete through the first three quotation marks
                                                       "   This deletes everything before the suggestion
                                                 ;     " Repeat motion; this jumps to the next \"
                                                  D    " Delete everything from there, leaving only the suggestion
                                                   ]yy " unimpaired.vim C string unescape to handle escaped '

As far as running goes, it works fine if you save it to a file named script and run with vim -s script input.txt on macOS, at least. It doesn't work if you add -u NONE, but it works fine if my .vimrc is empty. I assume it is using something from the system .vimrc to make the URL stuff work. This means, however, that it doesn't work in V, so no TIO link.

Some more test cases:

'what' => 'whataburger'
'what ' => 'what time is it' (Seriously? People Google that?)

What I really need is a way to open a URL with spaces in it. Replacing them with + first is just too many bytes!

\$\endgroup\$
  • 1
    \$\begingroup\$ should space be replaced by plus sign+? \$\endgroup\$ – tsh Apr 24 '17 at 1:59
  • 1
    \$\begingroup\$ @tsh You're right! Now somebody tell me how I can save 2 bytes and beat Dennis :) \$\endgroup\$ – Brian McCutchon Apr 24 '17 at 2:04
  • \$\begingroup\$ for netrw to work you need filetype plugin on \$\endgroup\$ – tbodt Apr 24 '17 at 2:19
  • 1
    \$\begingroup\$ You can paste the " register (default) in insert/command mode by doing <C-r>". You can shave off a few bytes by doing :r [url]?client=opera&q=^R" instead of q:ir [url]?client=opera&q=<esc>p. ^R is the actual byte sent when you press <C-r>, not the keys ^ and R together, so it only counts as one byte. \$\endgroup\$ – Ian Emnace Apr 24 '17 at 8:55
  • 1
    \$\begingroup\$ When I count the bytes I get 88. Also you can save bytes by changing the URL to http://google.com/complete/search?client=hp&q=your_query (client=gma => Plain JSON and shorter text.). \$\endgroup\$ – FatalMerlin Apr 24 '17 at 13:53
7
\$\begingroup\$

Python + requests 121 117 103 bytes

from requests import*
lambda s:get("http://google.com/complete/search?client=gma&q="+s).json()[1][0][0]
\$\endgroup\$
5
\$\begingroup\$

JavaScript, 109 Bytes

q=>fetch("//suggestqueries.google.com/complete/search?client=chrome&q="+q).then(r=>r.json()).then(r=>r[1][0])

Promise, you gotta love it, but man is it verbose! This answer uses fetch(), a promise-based fetch API present in modern browsers. Promises work by establishing handlers for async actions at the beginning, like callbacks, but better. The .then() takes a function which will be called with the result of the async action. .then(r=>r.json()) uses the .json() response method to convert the text array to a manipulable variable, the second .then() just pulls the first response.

Usage:

S = q=>fetch("//suggestqueries.google.com/complete/search?client=chrome&q="+q).then(r=>r.json()).then(r=>r[1][0])

S("node.js").then(console.log); // Prints the result to the debug console
\$\endgroup\$
  • 2
    \$\begingroup\$ .then(r=>r.json()).then(r=>r[1][0]) -> .then(r=>r.json()[1][0]) Enjoy 11 characters less ;-) \$\endgroup\$ – Stephan Bijzitter Apr 24 '17 at 13:23
  • \$\begingroup\$ I've tried in Firefox 52 and Chrome 57, on this page, Google's homepage, and about:blank, and I just keep getting CORS errors. Have you gotten it to work successfully? \$\endgroup\$ – ETHproductions Apr 24 '17 at 15:35
  • \$\begingroup\$ @ETHproductions Yes, there are CORS problems, you must execute on the domain suggestqueries.google.com \$\endgroup\$ – MayorMonty Apr 24 '17 at 19:32
  • \$\begingroup\$ @StephanBijzitter .json() returns a Promise, it's async, for some reason \$\endgroup\$ – MayorMonty Apr 24 '17 at 19:33
  • \$\begingroup\$ Indeed it works there, thanks! \$\endgroup\$ – ETHproductions Apr 24 '17 at 19:36
1
\$\begingroup\$

C#, 192 112 111 Bytes

Saved 80 Bytes thanks to @TheLethalCoder. Thanks for reformatting my code, I didn't know it was allowed to just leave off the surrounding Class and Method Body :)

Saved another Byte by replacing gma by hp, as it doesn't matter for the parsing and there is just some gibberish before the response body.

I litterally brute-forced the API to find gma and hp.

s=>new System.Net.WebClient().DownloadString("http://google.com/complete/search?client=hp&q="+s).Split('"')[3];
\$\endgroup\$
1
\$\begingroup\$

Groovy, 122 bytes

{Eval.me(new URL("http://suggestqueries.google.com/complete/search?client=chrome&q="+it).text.split(",\\{")[0]+"]")[1][0]}

Basically:

  1. Get the text from the end-point.

  2. Remove the part with the brackets at the end, this isn't valid syntax.

  3. Parse the remaining bit as a groovy array.

  4. Grab the second element of the result array.

enter image description here

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

PowerShell, 133 115 bytes

([net.webclient]::new().downloadstring("http://google.com/complete/search?client=gma&q=$_")|convertfrom-json)[1][0]

Sample run

Windows CMD command line:

powershell.exe -c "'code golf l'|%{([net.webclient]::new().downloadstring(""""http://google.com/complete/search?client=gma&q=$_"""")|convertfrom-json)[1][0]}"

PowerShell console:

'code golf l'|%{([net.webclient]::new().downloadstring("http://google.com/complete/search?client=gma&q=$_")|convertfrom-json)[1][0]}
\$\endgroup\$
1
\$\begingroup\$

R, 111 bytes

Long time since I last came here but giving it a shot:

jsonlite::fromJSON(readLines(url(paste0("http://google.com/complete/search?client=gma&q=",scan(,"")))))[[2]][1]

Using the package jsonlite to convert the string fetched from readLines() into a list object.

Subsequently extract the second element, e.g (gives a warning that we don't have to care about):

> jsonlite::fromJSON(readLines(url(paste0("http://google.com/complete/search?client=gma&q=",scan(,"")))))[[2]][1]
1: "how to"
2: 
    Read 1 item
[[1]]
[1] "how to make slime"

Warning message:
    In readLines(url(paste0("http://google.com/complete/search?client=gma&q=",  :
                                incomplete final line found on 'http://google.com/complete/search?client=gma&q=how to'
\$\endgroup\$
0
\$\begingroup\$

C#, 127 bytes

s=>new System.Net.WebClient().DownloadString("http://suggestqueries.google.com/complete/search?client=gma&q="+s).Split('"')[3];

Complete and formatted version:

static void Main()
{
    System.Func<string, string> f = s =>
        new System.Net.WebClient()
                      .DownloadString("http://suggestqueries.google.com/complete/search?client=gma&q="+s)
                      .Split('"')[3];

    System.Console.WriteLine(f("you"));
    System.Console.ReadLine();
}
\$\endgroup\$
  • \$\begingroup\$ Thanks for the hint about leaving of the Method and Class Body! \$\endgroup\$ – FatalMerlin Apr 24 '17 at 15:03

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.