The challenge is simple

Write a script that, when given a string input, will hash the string using the MD2 hashing algorithm, and then return either a positive integer or negative integer output based on which character set below is more common in the resulting hash as a hexadecimal string:

01234567 - (positive)
89abcdef - (negative)
  • The input will always be a string, but may be of any length up to 65535
  • The entire input, whitespace and all, must be hashed
  • For the purposes of this challenge, the integer 0 is considered neither positive nor negative (see tie output)
  • The more common set is the one who's characters are more common within the 32 character hexadecimal hash string
  • Your output may contain trailing whitespace of any kind, as long as the only non-whitespace characters are a valid truthy or falsey output
  • In the event of a tie, where the hexadecimal string contains exactly 16 characters from each set, the program should output a 0

I/O Examples

Input: "" (Empty String)
Hash: 8350e5a3e24c153df2275c9f80692773
Output: 1

Input: "The quick brown fox jumps over the lazy cog" (Without quotes)
Hash: 6b890c9292668cdbbfda00a4ebf31f05
Output: -1

Input: "m" (Without quotes)
Hash: f720d455eab8b92f03ddc7868a934417
Output: 0

Winning Criterion

This is , fewest bytes wins!

  • 1
    \$\begingroup\$ It would be good to link to or ideally explain the MD2 hashing algorithm in the challenge specification to make it self contained. \$\endgroup\$ Apr 19, 2017 at 15:28
  • \$\begingroup\$ @MartinEnder Will do! \$\endgroup\$
    – Mayube
    Apr 19, 2017 at 15:29
  • \$\begingroup\$ I think it would be fair to simply accept three distinct values for win, lose, and tie \$\endgroup\$ Apr 19, 2017 at 15:45
  • \$\begingroup\$ @mathjunkie true, probably shouldn't be changing the spec so much, but I guess just having 1, 0 or -1 is the best way \$\endgroup\$
    – Mayube
    Apr 19, 2017 at 15:47
  • 3
    \$\begingroup\$ This strikes me as a chameleon challenge. Either your language has a build-in or library to do MD2 and the rest is simple character counting, or it doesn't and you have to implement it yourself. \$\endgroup\$
    – xnor
    Apr 20, 2017 at 0:20

9 Answers 9


Mathematica, 43 bytes


Outputs the number of digits in 01234567 minus the number of digits in 89abcdef.

  • 1
    \$\begingroup\$ Too bad that 3E is between 8 and 9 and not between 7 and 8. :| \$\endgroup\$ Apr 19, 2017 at 15:54

JavaScript (ES6), 731 bytes

This monster is implementing the MD2 algorithm, so it's embarrassingly long. Based on js-md2 by Chen Yi-Cyuan.

let f =

m=>{L=x=s=b=0,n=m.length,M=[],X=[],C=[],S=[...atob`KS5DyaLYfAE9NlSh7PAGE2KnBfPAx3OMmJMr2bxMgsoem1c8/dTgFmdCbxiKF+USvk7E1tqe3kmg+/WOuy/ueqloeZEVsgc/lMIQiQsiXyGAf12aWpAyJzU+zOe/95cD/xkws0iltdHXXpIqrFaqxk+4ONKWpH22dvxr4px0BPFFnXBZZHGHIIZbz2XmLagCG2Alra6wufYcRmFpNEB+D1VHoyPdUa86w1z5zrrF6iYsUw1uhSiECdPfzfRBgU1Satw3yGzBq/ok4XsIDL2xSniIlYvjY+ht6cvV/jsAHTny77cOZljQ5KZ3cvjrdUsKMURQtI/tHxrbmY0znxGDFA`].map(c=>c[O='charCodeAt']());for(l=1;l-2;){for(j=19;j--;)M[j]=M[16+j]||0;for(i=s;i<16;x++)L=(x-n||(b+=i-s,s=i-16,l=2),C[i]^=S[(M[i++]=x<n?m[O](x):16-(b&15))^L]);for(i=0;i<l;i++){for(j=16;j--;)X[32+j]=(X[16+j]=(i?C:M)[j])^X[j];for(t=j=0;j<18;t=t+j++&255)for(k=0;k<48;)t=X[k++]^=S[t]}}for(i=16,n=-i;i--;)n+=!(X[i]&8)+!(X[i]&128);return n}

console.log(f('The quick brown fox jumps over the lazy cog'))

  • \$\begingroup\$ Beat me to it. Really nice effort. \$\endgroup\$
    – Luke
    Apr 20, 2017 at 6:13
  • \$\begingroup\$ Props for, thus far, being the only one to actually implement the full MD2 algorithm rather than using built-in functions. \$\endgroup\$
    – Mayube
    Apr 20, 2017 at 9:50
  • 1
    \$\begingroup\$ Highest byte answer deserving of more points. \$\endgroup\$ Apr 20, 2017 at 13:51

Python 2 + Crypto, 108 99 93 91 87 78 bytes

Python doesn't have a native builtin for MD2.

from Crypto.Hash import*
lambda s:sum(x<'8'for x in MD2.new(s).hexdigest())-16

Saved 12 bytes thanks to @ovs.
Saved 9 bytes thanks to @FelipeNardiBatista.

  • \$\begingroup\$ lambda s:cmp(sum((int(x,16)<8)-.5for x in MD2.new(s).hexdigest()),0) should reduce the byte count to 93 \$\endgroup\$
    – ovs
    Apr 19, 2017 at 17:45
  • \$\begingroup\$ @ovs Very clever! \$\endgroup\$
    – mbomb007
    Apr 19, 2017 at 20:08
  • \$\begingroup\$ sum(x<'8'for x ...... \$\endgroup\$ Apr 20, 2017 at 12:35
  • \$\begingroup\$ lambda s:sum(x<'8'for x in MD2.new(s).hexdigest())-16 for 78. the output can be any number, not just -1,0,1 \$\endgroup\$ Apr 20, 2017 at 12:45

Java 8, 173 bytes

-4 thanks to dzaima

-128 thanks to Oliver, this is basically his answer now.

a->{String h="";for(byte b:java.security.MessageDigest.getInstance("MD2").digest(a.ge‌​tBytes()))h+=h.forma‌​t("%02x",b);return h.codePoints().filter(c->c>47&&c<56).count()-16;}

Positive for truthy. Negative for falsy. 0 for 0.

  • 1
    \$\begingroup\$ You can save 4 bytes by removing the enclosing brackets of for and if \$\endgroup\$
    – dzaima
    Apr 19, 2017 at 16:48
  • 1
    \$\begingroup\$ bytes to hex can be golfed: String s="";for(byte b:bytes)h+=h.format("%02x",b);. Also, you don't need to write a full program, but a lambda suffice: a->{... return x;}. Finally the for loop can be replaced by int x=s.codePoints().filter(c->c>47&&c<56).count();. All in all, I get 173 for your algorithm, golfed: a->{String h="";for(byte b:java.security.MessageDigest.getInstance("MD2").digest(a.getBytes()))h+=h.format("%02x",b);return h.codePoints().filter(c->c>47&&c<56).count()-16;}. More golfing is possible, but this is a net improvement in byte count, isn't it? \$\endgroup\$ Apr 20, 2017 at 8:16
  • \$\begingroup\$ Some things to golf: println -> print and for(char c:s.toCharArray())if("01234567".contains(""+c))x++; -> for(String c:s.split(""))if("01234567".contains(c))x++; \$\endgroup\$ Apr 20, 2017 at 11:25
  • \$\begingroup\$ @OlivierGrégoire I don't know much about Java 8, I switched to Groovy/Grails around the same time. \$\endgroup\$ Apr 20, 2017 at 13:50

PHP, 50 Bytes

prints 1 for truthy and -1 for false and 0 for a tie


PHP, 58 Bytes

prints 1 for truthy and -1 for false and 0 for a tie

  • \$\begingroup\$ Sorry for all the spec changes, final output requirements are in now. Basically what you currently have but reversed (1 for truthy, -1 for falsey) which should be fairly easy as iirc in PHP -0 === 0 \$\endgroup\$
    – Mayube
    Apr 19, 2017 at 15:51
  • \$\begingroup\$ @Mayube this is too long 1 Byte more is enough. The best way is to specified the output by the possibilities of the language and not general \$\endgroup\$ Apr 19, 2017 at 16:09
  • 1
    \$\begingroup\$ echo 16<=>strlen(preg_filter("#[0-7]#","",hash(md2,$argn))); should do the trick without additional byte. \$\endgroup\$
    – Christoph
    Apr 20, 2017 at 6:57
  • 1
    \$\begingroup\$ Golfed version: <?=preg_match_all("/[0-7]/",hash(md2,$argn))<=>16; \$\endgroup\$
    – Christoph
    Apr 20, 2017 at 7:10
  • \$\begingroup\$ @Christoph I feel like an idiot that I have not think about preg_match_all \$\endgroup\$ Apr 20, 2017 at 11:47

Octave, 35 bytes


*Requires the latest version of Octave (at least 4.2).

Computes histcounts of the hash string with it's center of bins are 7 and 8 then computes the difference of counts.

  • \$\begingroup\$ Given it's been a few days I'll put yours up as the winning answer, if somebody comes along later with a shorter solution I can always change it. Well done! \$\endgroup\$
    – Mayube
    Apr 21, 2017 at 13:02
  • \$\begingroup\$ @Mayube Thanks! \$\endgroup\$
    – rahnema1
    Apr 21, 2017 at 16:35

PHP, 56 bytes


Java 137 130 124 123 bytes

a->{int c=32;for(int b:java.security.MessageDigest.getInstance("MD2").digest(a.getBytes()))c-=(b>>6&2)+(b>>2&2);return c;}

Test it online!

Basically, for each byte, we're asked to check against its 4th and 8th least significant bits. I don't go through the hex representation at all. So it seemed only natural to start playing with bits.

Values <0 are falsey, values >0 are truthy, value 0 is neither truthy or falsey. The usual truthy and falsey can't be applied to Java this time (because it can't be true or false or 0 with the rule if(<truthy>)), so I took the liberty to declare as such.


  1. 137 -> 130 bytes: golfed by using bit operations, removing 2 everytime I get a "falsy" bit.
  2. 130 -> 124 bytes: more bitwise operations
  3. 124 -> 123 bytes: replaced byte by int in the for loop declaration.

Tcl + Trf package, 79

package require Trf
puts [expr [regexp -all \[0-7\] [hex -m e [md2 $argv]]]-16]

Try it online. (Thanks @Dennis for adding Tcl to TIO.)


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.