25
\$\begingroup\$

Greetings, noble code golfers. Today you will resolve the most ancient and distinguished of debates - Emacs or Vim?

Your challenge is to take two search terms as input, and output which of those terms has the most Google search results. (This is obviously completely fair. What do you mean, biased?)

Here are some example inputs and outputs:

Input: emacs and vim
Output: vim (totally not creating any flamewars in the comments)

Input: google and microsoft
Output: google

Input: code golf stack exchange and code review stack exchange
Output: code golf stack exchange (yeah!)

And here are some edge cases just for fun (and for testing your solutions):

Input: About 1,000,000 results and About 100,000 results
Output: About 100,000 results

Input: This will autocotrect and Another testcase
Output: Another testcase (if you don't consider autocorrecting, then the first one will win)

For the following test cases, you must remove the # signs in the search terms first, since they rely on the term having a specific amount of results and posting the term here would ruin that.

Input: Thissear#chter#mhasno#results and Another testcase
Output: Another testcase (just a test for zero results)

Input: "These exact wo#rds do#n't exi#st# on the Internet" and Another testcase
Output: Another testcase (testing "s)

Input: Abo#ut 1,65#2,85#3,2#86 re#sults and Another testcase
Output: Another testcase (this one is tricky - the above search term has one result)

Input: "Abo#ut 4#8,234,8#75,14#7 res#ults" and Another testcase
Output: Another testcase (also tricky - no results, so it displays the search term)

You don't need to handle the corner-case of "quoted" searches returning "No results, showing results without quotes instead" because that would just be too complicated. You don't need to handle inputs with the same number of results either.

This is , so the shortest code in bytes will win!

\$\endgroup\$
4
  • \$\begingroup\$ Psst... you should change the accepted answer :D \$\endgroup\$
    – cat
    Mar 29 '16 at 21:11
  • \$\begingroup\$ @tac Alternatively, I can golf it down instead, which I did. ;) \$\endgroup\$
    – Doorknob
    Mar 29 '16 at 23:12
  • \$\begingroup\$ How flexible's the output / return value? Does it have to be a string, or can it be an array containing the string and the number of results it had, or an array containing just the string? \$\endgroup\$
    – cat
    Mar 30 '16 at 13:24
  • 3
    \$\begingroup\$ it's so clear than vim is better I was surprised on this question that anyone could believe that something is better \$\endgroup\$
    – Downgoat
    Apr 3 '16 at 0:14
5
\$\begingroup\$

Factor, 305 201 196 200 201 188 184 182 179 169 178 171 165 199 171 170 165 163 bytes

A language nearly as verbose as Java, beating Ruby... and Powershell! :D

Better regex, now. Thanks to @fede s. for 5 bytes off!

[ dup [ url-encode "google.com/search?nfpr=1&q="prepend http-get R/ s">About [\d,]+/ first-match " "split second 10 >base ] map zip [ last ] sort-with last first ]

Or 159 157 if the output can be like { "vim" 9782948234 }:

[ dup [ url-encode "google.com/search?nfpr=1&q="prepend http-get R/ s">About [\d,]+/ first-match " "split second 10 >base ] map zip [ last ] sort-with last ]

On the other hand, if we want to be unkillable, for 199 196 193 bytes:

[ dup [ url-encode "google.com/search?nfpr=1&q="prepend scrape-html nip dup "resultStats"find-by-id-between second text>> " "split second string>number ] map zip [ last ] sort-with last first ]

Unkillable because it parses HTML, so way more robust than the answers using regex.

\$\endgroup\$
9
  • 1
    \$\begingroup\$ And python. Good for Factor. :P \$\endgroup\$ Mar 29 '16 at 21:13
  • \$\begingroup\$ @EasterlyIrk so close yet so far \$\endgroup\$
    – cat
    Mar 30 '16 at 13:07
  • \$\begingroup\$ @EasterlyIrk I did it! \$\endgroup\$
    – cat
    Mar 30 '16 at 13:20
  • 1
    \$\begingroup\$ Someone should make a Factor golfing dialect, so much whitespace, words so long... Well done, man! \$\endgroup\$
    – fede s.
    Apr 3 '16 at 1:57
  • 1
    \$\begingroup\$ Thank you for the unkillable method. It's actually shorter in powershell than using a regex. (Yet still 2 bytes longer than your regex answer). I wouldn't call powershell succint though, it's command names are rarely short (iwr happens to be a default alias for invoke-webrequest and sort for sort-object, otherwise it'd be that much longer) \$\endgroup\$ Apr 6 '16 at 20:06
7
\$\begingroup\$

Ruby, 203 180 bytes

->*s{s.map{|x|[(open("http://www.google.com/search?nord=1&q=#{URI.escape x}&nfpr=1").read.match(/s">(About )?([\d,]+) result/)||[?0])[-1].split(?,).join.to_i,x]}.max[1]}

+11 bytes for the -ropen-uri flag (plus space).

Input is taken as two arguments.

URL explanation:

  • ?nord=1: prevent auto-redirect from HTTP to HTTPS
  • &q=#{URI.escape x}: escape the query so "s work
  • &nfpr=1: no autocorrect

The whole map turns ['emacs','vim'] into [[2150000, 'emacs'], [14900000, 'vim']]. (You can see this by changing the .max[1] at the end to .inspect.) Then, the max is taken, which will grab the one with the most results, and [1] is used to get the search term.

\$\endgroup\$
6
  • \$\begingroup\$ It doesn't work for me. ideone.com/UqEyBn \$\endgroup\$
    – TheDoctor
    Apr 8 '14 at 17:05
  • \$\begingroup\$ @TheDoc It doesn't work on Ideone - run it on actual Ruby \$\endgroup\$
    – Doorknob
    Apr 8 '14 at 17:09
  • \$\begingroup\$ You can save a few more bytes by requiring in the command ruby -ropen-uri instead of in the file. \$\endgroup\$
    – Shelvacu
    Mar 26 '16 at 0:01
  • \$\begingroup\$ Why won't this (and the other regex answers) break on searches like "About 100,000,000 results"? \$\endgroup\$
    – cat
    Apr 2 '16 at 23:26
  • \$\begingroup\$ @cat Note the s"> at the start of the regex. That makes sure the result count is preceded by a certain HTML tag (I don't remember which one; probably something like <span id="num-results"> or something). \$\endgroup\$
    – Doorknob
    Apr 3 '16 at 14:51
7
\$\begingroup\$

Of the text editors mentioned in the problem, only one of them can solve this on its own...

Emacs: 137 keystrokes

<C-o><C-u><C-k>(if(<<C-y><C-y><M-<><C-n><F3><C-a>http://google.com/search?nfpr=1&q=<C-S-e><M-x>r-st<RET> <RET>+<RET><C-a><C-k><M-x>b-em<RET><C-y><RET><C-x><C-q><C-s><RET>ts"><RET><M-z><<C-x>0<C-y>0 r<C-a><C-M-s><RET>[0-9]<RET><C-b><M-z> <C-a><C-y><C-k><C-S-a><M-x><up><up><RET>,<RET><RET><F4><C-n><F4><C-e>)(next-line)())<C-x><C-e><C-n><C-a><C-k><C-x>h<DEL><C-y>

It expects the first search terms to be on the first line and the second search terms to be on the second line, with the cursor at the beginning of the buffer.

For those unfamiliar with Emacs,

  • C-s means Ctrl-S.
  • M-z means Alt-Z (Alt is likely your meta key)
  • M-< means Alt-< or Alt-Shift-,
  • C-S-e means Ctrl-Shift-e

For those familiar with Emacs,

  • Start emacs with emacs -q. That doesn't load your .emacs file, so any fancy packages won't intefere with this.

Explanation

  1. Write the beginning of the elisp statment shell

    • <C-o><C-u><C-k> Saves the arguments with a newline
    • (if(<<C-y><C-y> Write the start of the if statement and places 2 copies of the arguments
    • <M-<><C-n> Move to the second line
  2. Define the HTTP macro. This converts the argument to a Google search URL and then returns the number of search results.

    • <F3> Start defining the keyboard macro
    • <C-a> Move to the start of the search term.
    • http://google.com/search?nfpr=1&q= Prepend the search URL
    • <C-S-e><M-x>r-st<RET> <RET>+<RET> Replace all the spaces with + signs.
    • <C-a><C-k><M-x>b-em<RET><C-y><RET> Emacs retrieve the raw HTML (b-em is short for browse-url-emacs)
    • <C-x><C-q> Make the file writable (required so the macro doesn't error ou t)
    • <C-s><RET>ts"><RET> Move to the number of results div (need to do a regular search because emacs macros rely on isearch to work)
    • <M-z><Cut the text of of the diff (this is why the was required)
    • <C-x>0 Switch back to the original buffer
    • <C-y>0 r;; Put the results back on the line ('0 r' handles no results)
    • <C-a><C-M-s><RET>[0-9]<RET><C-b><M-z> <C-a><C-y><C-k>;; Extract the number from the string.
    • <C-S-a><M-x><up><up><RET>,<RET><RET> Strips commas out of the number
    • <F4> Finish the keyboard macro
  3. Move down and execute the keyboard macro on the next line.

    • <C-n> Goes to the next line
    • <F4> Repeat the macro once.
  4. Finish up the elisp statement and execute it

    • <C-e>)(next-line)()) Finish up the elisp statement
    • <C-x><C-e> Evaluate the elisp command
    • <C-n><C-a><C-k> Kill the winning argument
    • <C-x>h<DEL> Delete everything else
    • <C-y> Paste the winning argument

Running It Yourself

Luckily you don't have to type all those keystrokes in perfectly! The meat and potatoes is all in a macro that you can just copy and paste. The macro can be copy and pasted into emacs!

1.Edit the keyboard macro <C-x><C-k><C-e>
2.Paste this into the whole buffer (paste should be <C-y>)

;; Keyboard Macro Editor.  Press C-c C-c to finish; press C-x k RET to cancel.
;; Original keys: C-a http://google.com/search?nfpr= 1&q= S-C-e M-x r-st RET SPC RET + RET C-a C-k M-x b-em RET C-y RET C-x C-q C-s RET ts"> RET M-z < C-x 0 C-y 0 SPC r C-a M-C-s [0-9] 5*DEL RET [0-9] RET C-b M-z SPC C-a C-y C-k S-C-a M-x 2*<up> RET , 2*RET
Command: last-kbd-macro
Key: none
Macro:
C-a         ;; move-beginning-of-line
http://google.com/search?nfpr=  ;; self-insert-command * 30
1&q=            ;; self-insert-command * 4
S-C-e
M-x         ;; execute-extended-command
r-st            ;; self-insert-command * 4
RET         ;; newline
SPC         ;; self-insert-command
RET         ;; newline
+           ;; self-insert-command
RET         ;; newline
C-a         ;; move-beginning-of-line
C-k         ;; kill-line
M-x         ;; execute-extended-command
b-em            ;; self-insert-command * 4
RET         ;; newline
C-y         ;; yank
RET         ;; newline
C-x C-q         ;; read-only-mode
C-s         ;; isearch-forward
RET         ;; newline
ts">            ;; self-insert-command * 4
RET         ;; newline
M-z         ;; zap-to-char
<           ;; self-insert-command
C-x 0           ;; delete-window
C-y         ;; yank
0           ;; self-insert-command
SPC         ;; self-insert-command
r           ;; self-insert-command
C-a         ;; move-beginning-of-line
M-C-s           ;; isearch-forward-regexp
RET         ;; newline
[0-9]           ;; self-insert-command * 5
RET         ;; newline
C-b         ;; backward-char
M-z         ;; zap-to-char
SPC         ;; self-insert-command
C-a         ;; move-beginning-of-line
C-y         ;; yank
C-k         ;; kill-line
S-C-a
M-x         ;; execute-extended-command
2*<up>          ;; previous-line
RET         ;; newline
,           ;; self-insert-command
2*RET           ;; newline
  1. Type <C-c><C-c> to save the macro.
  2. If following the explanation steps, replace step 2 with <F4> to run the macro (or just run it on its own to try)

Caveats

  1. You can't run the macro on the same search twice without killing the buffer the HTML gets loaded into. Kill the buffers
    • <C-x><k> search<TAB>
    • Choose one of the buffers in this list to kill.
    • Repeat for all the buffers beginning with "search"
  2. If you run the macro too much, Google will think you are a robot and block access for atime
    • If the macro returns something like <input type="submit" name="submit" value="Submit"...>, then this likely occurred.
    • You can confirm it by looking at the raw HTML (<C-x><C-b> and choose the buffer with the search term in it).
    • If you see stuff about robots and captcha, Google's blocking you. It's not my fault.
\$\endgroup\$
2
  • \$\begingroup\$ This is really cool! Of the text editors mentioned in the problem, only one of them can solve this on its own... is that even true? are there really no HTTP libraries for vimscript? \$\endgroup\$
    – cat
    Jun 21 '17 at 22:36
  • \$\begingroup\$ There's at least nothing in vanilla vim, but brief googling didn't pop up any vimscript HTTP libraries. I can't imagine why anyone would actually write that when you could just read the results of curl and get the same effect. (but then your answer should indicate that it's vim+curl). \$\endgroup\$
    – Dominic A.
    Jun 24 '17 at 11:40
3
\$\begingroup\$

Java, 828 800 783 744 739 687 bytes

import java.net.*;import java.util.*;import java.util.regex.*;interface G{static Scanner s(String a)throws Exception{URL u=new URL("http://google.com/search?q="+a);HttpURLConnection c=(HttpURLConnection)u.openConnection();c.addRequestProperty("User-Agent","Mozilla/4.0");return new Scanner(c.getInputStream());}static void main(String[]r)throws Exception{String a,b;String c=s(a=r[0]).useDelimiter("\\Z").next(),d=s(b=r[1]).useDelimiter("\\Z").next();Matcher m=Pattern.compile("ut ([0-9,]+) res").matcher(c);m.find();long i=new Scanner(m.group(1)).nextLong();m=Pattern.compile("ut ([0-9,]+) res").matcher(d);m.find();long j=new Scanner(m.group(1)).nextLong();System.out.print(i>j?a:b);}}
\$\endgroup\$
4
  • \$\begingroup\$ Holy cats. The imports alone are 79 bytes... perhaps you should try Groovy? :P \$\endgroup\$
    – cat
    Mar 30 '16 at 2:01
  • 1
    \$\begingroup\$ I'm really entertained by the fact you have to set the user-agent string yourself. Like, as if Java wasn't verbose enough \$\endgroup\$
    – cat
    Mar 30 '16 at 2:02
  • \$\begingroup\$ Because google gives a 403 if you don't. \$\endgroup\$ Mar 30 '16 at 2:03
  • 2
    \$\begingroup\$ Why not take input from args instead of StdIn? \$\endgroup\$
    – Pavel
    Feb 8 '17 at 21:09
2
\$\begingroup\$

Python 3, 227 226 208 213 226 220 221 206 202 200 198 bytes

import re,requests as r,urllib.parse as u
lambda*t:sorted(zip(map(lambda a:int(re.findall("s\">About ([\d,]+)",r.get("http://google.com/search?q="+u.quote(a)).text)[0].replace(",","")),t),t))[-1][1]

Assign the lambda to something to call it.

Uses the requests library.

Ungolfed:

import re, requests as r, urllib.parse as u
lambda*t:
  sorted(
  list(
      zip(map(
              lambda a: int(re.findall("About ([\d,]+)",
               r.get("http://google.com/search?q="+u.quote(a)).text)[0].replace(",","")),
              t
          ),
       t)
   )
)[-1][1]
\$\endgroup\$
4
  • \$\begingroup\$ This doesn't work on my machine even after installing requests: NameError: name 'quote' is not defined \$\endgroup\$
    – Shelvacu
    Mar 26 '16 at 0:19
  • \$\begingroup\$ @shelvacu Oops, I'm smart, I forgot to change quote back to urllib.parse.quote after an absolute import. \$\endgroup\$
    – cat
    Mar 26 '16 at 0:20
  • \$\begingroup\$ did you test this? It also looks like google.co/search gives 404 whereas google.com/search works \$\endgroup\$
    – Shelvacu
    Mar 26 '16 at 0:26
  • \$\begingroup\$ @shelvacu yes, I tested it, it gives the same results as the ruby answer and the question says. \$\endgroup\$
    – cat
    Mar 26 '16 at 0:26
1
\$\begingroup\$

Powershell, 175, 172 bytes

($args|%{[pscustomobject]@{'a'=$_;'b'=[int]((iwr "google.com/search?nord=1&q=$_&nfpr=1").parsedhtml.getelementbyid('resultstats').innertext-split" ")[1]}}|sort -des b).a[0]

Showing the score as well as the name would cut 2 more bytes.

This uses the same unkillable feature as the 196 Byte Factor answer (Parsed HTML) and cuts down from the previous regex answer.

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

Racket, 360 337 bytes

#lang racket(require net/url net/uri-codec)(λ(t)(cddr(sort(map list t(map(lambda(a)(string->number(string-replace(list-ref(string-split(car(regexp-match#px"s\">About [\\d,]+ res"(call/input-url(string->url(string-append"http://google.com/search?nfpr=1&q="(uri-encode a)))(curry get-pure-port)port->string)))" ")1)",""")))))#:key cdr <)))

0.o

There's a reason they call it Lost In a Sea of Parentheses.

Ungolfed:

#lang racket
(require net/url)
(require net/uri-codec)

(define (open-url term)
  (call/input-url
   (string->url (string-append "http://" term))
   (curry get-pure-port #:redirections 5)
   port->string))

(define (get-result term)
  (string->number
   (string-replace
    (list-ref
     (string-split
      (car (regexp-match #px"s\">About [\\d,]+ results" (open-url (string-append "google.com/search?nfpr=1&q=" (uri-encode term)))))
      " ")
     1)
    "," "")))

(define (zip a b) (map list a b))

(define (google-fite terms) (cddr (sort (zip terms (map get-result terms))) #:key cdr <))
\$\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.