text:
Condense these page numbers!
Disclaimer: while I have been on this site for entertainment purposes for a little while now, this is my first question, so please forgive any minor errors.
Background
When assigning us homework, my teacher is really annoying and writes out all the problems we have to do individually. As such, it takes me forever to copy down which problems I have to do. I thought to make my life easier, I would send him a program that could make the list of problems take up less space.
While writing down a list of page or problem numbers, we use a dash to denote a range. For example, 19-21 becomes 19, 20, 21. If there is a gap in between, two comma-separated ranges are used: 19-21, 27-31 becomes 19, 20, 21, 27, 28, 29, 30, 31.
Right about now, you're probably thinking: "this seems pretty trivial". In fact, this has already been answered here and here.
However, there is a catch. If we have a range with equal consecutive digits, the repeated digits can be left out. For example: 15, 16, 17 becomes 15-7, and 107, 108, 109 becomes 107-9. For a bonus, if the last consecutive equal digit is 1 greater and the upper limit's last digit is less than or equal to that of the lower, the following can be omitted (sorry if that sounded confusing; perhaps some examples will clear it up). 109-113 becomes 109-3, as a lower last digit implies increasing the 10s place.
Challenge
Your program should take a list of integers via input (whatever is standard for your language, or a function).  You can decide whether this list is comma-separated, space-separated, or as an actual list/array.
Output the shortest way (first sorted by number of ranges, then the sum of the characters included in the ranges) to represent that list using this notation. Each dashed range must be on the same line, but the ranges can be separated by commas or newlines (trailing newlines or commas are allowed). These ranges must be in order.
Since our school Wi-Fi is terrible, I have to make the file as small as possible in order to send it to him. The shortest code (in bytes) wins.
Bonuses
My teacher is sloppy, so there are a few things that would help him out.
Multiple bonuses stack through multiplication, e.g. a -10% bonus (x 90%) and a -25% (x 75%) bonus = 90% * 75% = x 67.5% (-32.5% bonus).

Sometimes he puts them in the wrong order (he's not a math teacher). Take a -20% bonus if your program can accept integers that are not sorted least-to-greatest.
Our book is weird, and each section starts counting the problems at -10. If your program can accept negative numbers, take a -25%.
If it accepts the bonus of a lower last digit increasing 10's place, e.g. 25-32 reducing to 25-2, take a -50% bonus.

Test Cases
In:  1, 2, 3, 4, 5
Out: 1-5

In:  3, 4, 5, 9, 10, 11, 12
Out: 3-5, 9-12

In:  149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160
Out: 149-60

In: 1 2 3 4
Out: 1-4

For bonuses:

In: 109, 110, 111, 112, 113
Out: 109-3

In:  19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29
Out: 19-9

In: -3, -2, -1, 0, 1, 2
Out: -3-2

In: -3, -2, -1
Out: -3--1

An answer will be accepted on Saturday, 19 December 2015.
GLHF!

Why is the output in the third test case not 1-4 9-2?

What should be output for a program that (a) does and (b) does not take the 50% bonus, for 149 150 151 152 153 154 155 156 157 178 159 160?

@ThomasKwa whichever results in the least ranges, so 149-60

The second result, 10-9, makes no sense to me. Shouldn't it be simply 10, 19?

How should negative numbers be represented? -5--3?

@Mego Since there will always be a - or space between numbers, there should be no ambiguity, so having a dash and negation sign next to each other is fine.

I could've sworn there's another question just like this, but I can't find it...

I should hope not... I spent 15 minutes looking for one. If there is one, I think it's safe to say that the question is long dead.

I feel like this same question keeps getting asked. What's going on?

I think this is the related question everybody is thinking of. That one turns ranges into lists though.

Are functions allowed?

@TheCoffeeCup that's fine.

Also, the last in/out doesn't make sense. Do you mean In: 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29?

Can I request the list be input one element at a time 12<enter>13<enter>14... and terminated by a character?

@TheCoffeeCup fixed. I should have programmatically generated these.

@sysreq that's fine, I'm not particularly picky about the format of the input (anymore).

The first 'bonus' example has nothing to do with the bonuses

Can we get a clarification on whether duplicates and single pages should be handled, since none are now included in test cases?

Another thing - the text says that the penultimate digit for the ending page of the range should be cut if it's lower than that of the start page, but the test case says 19-9 for 19,20,...,29 and not 19-29 as the text implies. So which is correct?

Can we get a lot more test cases... the test cases don't even cover all the bonuses. I think this would clarify a lot.

In the last paragraph of section Background, at one point the last digit is asked to be "less than or equal". Still, two questions for OP:
If indeed the last digit being not only lower but also possibly equal implies the previous digit increasing, don't 19 and 19,20,21,22,23,24,25,26,27,28,29 both produce 19-9?
Sometimes you seem to want to generalize to higher carries than 10, f.x. 99,100,101,102 ^= 99-2. Is this to be respected for the bonus?

I think 19 shall become 19 and 19,20,21,22,23,24,25,26,27,28,29 19-9. I also generalized that behaviour to any carry so that the number of digits printed depends only on the difference of start and end value: 0 -> "",  1-10 -> 1 digit, 11-100 -> 2 digits, etc..

LabVIEW, 97*0.8*0.75*0.5 = 29.1 LabVIEW Primitives
this works by counting upwards if sucessive elemts are 1 apart and then creates a string from the the number and the number - count modulo 10 and some multiplication cause negatives are a bitch.
The gif showcases an input of 8,9,10,11 and outputs 8-1. For input -5,-4,-3,1,3,4,5 -5--3,1,3-5comes out.

Really, counting it as each for loop/while loop/if/whatever is 1 primitive isn't fair because in languages like JS, they count as more than 1 byte...

@ev3commander anything's fair if it comes with a cool animated diagram!

thats why its in primitives not bytes. Also theres a lot of wiring going on so the loops actaully are 2 or 3 at least and also another 3 per shift register + initialisation.

@cyoce Noooooope. I could create a new language called "CondPgNmbrs" and add some diagram of how the language works, and that would be "fair"...

by standard golf rules you can do that, its just boring

@ev3commander Actually, if the language is newer than the challenge you are not allowed to use it for competitive reasons.

@Adnan actually at least most of the time newer languages are allowed

@Eumel Even for competitive reasons? Can you give an example?

ok most of the time might have been a slight exxageration, but every once in a while i stumble upon a set of rules that allows newer languages and i always regarded those as the standard rules.

@Adnan I know, that's my point. not "anything's fair with a cool animated diagram"...

C++11, 451 * 80% * 75% * 50% = 135.3 bytes
Saved 9 bytes thanks to @kirbyfan64sos.
Saved 19 bytes thanks to @JosephMalle and @cat.
Saved 11 bytes thanks to @pinkfloydx33.
#include<vector>
#include<cmath>
#include<algorithm>
#include<string>
#define T string
#define P append
using namespace std;T f(vector<int>v){sort(v.begin(),v.end());T r=to_T(v[0]);int b=1;int m=v[0];for(int i=1;i<=v.size();i++){if(i!=v.size()&&v[i]==v[i-1]+1){if(!b){m=v[i-1];}b=1;}else{if(b){T s=to_T(v[i-1]);r.P("-").P(s.substr(s.size()-(v[i-1]-m==1?1:log10(v[i-1]-m)),s.size()));}if(i!=v.size()){r.P(", ").P(to_T(v[i]));}b=0;}}return r;}

This qualifies for all the bonuses.
Sample parameter test and result:
In:  [1, 2, 3, 4, 5]
Out: 1-5

In:  [3, 4, 5, 9, 10, 11, 12]
Out: 3-5, 9-12

In:  [149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160]
Out: 149-60

In:  [1, 2, 3, 4]
Out: 1-4

In:  [109, 110, 111, 112, 113]
Out: 109-3

In:  [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
Out: 19-9

Why not use int instead of unsigned int? Saves 9 bytes.

@kirbyfan64sos Thanks, didn't notice that.

+1 always like to see C++. I can't test this, but I don't think you need iostream

I don't think you need iostream either, but gcc gave: a.cpp: In function ‘std::string f(std::vector<int>)’: a.cpp:8:83: error: ‘to_string’ was not declared in this scope

@cat Make sure it's updated enough that it supports the C++11 standard. 4.3-ish should be good with -std=c++11; >= 5.0 has it on by default (actually it's -std=gnu11, but close enough).

@Mego All -std=c++11 does is give me multiple screenfuls of errors and gcc saying Segmentation fault (core dumped). This is gcc 4.8.4 on Linux. (Not that it matters that it won't compile for me)

@cat That would be because this is a function, not a full program. Add something like int main(){cout<<f({1,2,3,4,5})<<endl;return 0;} to the code and it'll be a full program. With that addition, it compiles and runs fine under gcc 5.2.0 on Linux.

@Mego Oh, duh. I don't know C++ but I saw the using and the includes and assumed a instantly compilable answer.

Wouldn't this give unsigned-signed mismatch? If it does, use C++11 or above and auto instead of int

@ev3commander yes, but it's a warning, and it seems to run fine with the warning. The question didn't state that it had to be warning-free.

@TheCoffeeCup  just tried compiling in vs, it works

you can save 13 bytes using int b; swapping the if statements if(b) => if(!b) (and vise-versa), replacing the b=true with b=0 and the b=false with b=1

why not claim the two extra from int b; (no =1) and inverting the rest? compiles with warning, sure... but it works

Ruby, 120 118 * 0.8 * 0.75 * 0.5 = 35.4 bytes

Takes command-line arguments as input (commas are okay); prints one range per line to standard output.
c=(b=(a=$*.map(&:to_i).sort).map &:succ)-a
puts (a-b).map{|m|(m<n=c.shift-1)?"#{m}-#{m<0?n:n%10**"#{n-m-1}".size}":m}

With whitespace/comments:
c=(
  b=(
    # a is the sorted input
    a=$*.map(&:to_i).sort
  # b is the set of successors of elements of a
  ).map &:succ
# c=b-a is the set of not-quite-least upper bounds of our ranges
)-a

# a-b is the set of greatest lower bounds of our ranges
puts (a-b).map {|m|
  # for each range [m,n], if there are multiple elements
  (m < n = c.shift-1) ?
    # yield the range, abbreviating n appropriately if positive
    "#{m}-#{m<0 ? n : n % 10 ** "#{n-m-1}".size}" :
    # in the one-element case, just yield that
    m
}

Test cases
$ ruby homework.rb 1, 2, 3, 4, 5
1-5

$ ruby homework.rb 3, 4, 5, 9, 10, 11, 12
3-5
9-2

$ ruby homework.rb 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160
149-60

$ ruby homework.rb 1 2 3 4
1-4

$ ruby homework.rb 109, 110, 111, 112, 113
109-3

$ ruby homework.rb 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29
19-9

Features not covered by test cases
Unordered input & single-element ranges:
$ ruby homework.rb 2 17 19 22 0 1 8 20 18
0-2
8
17-0
22

Negative ranges (not possible to abbreviate the larger number with these):
$ ruby homework.rb -17 -18 -19 -20 -21
-21--17

Abbreviation of arbitrary numbers of digits (ordinary bash expansion used for the input here):
$ ruby homework.rb {1234567..1235467} 2345999 2346000 2346001
1234567-467
2345999-1

I believe you can replace ((n=c.shift-1)>m) with m<n=c.shift-1

Javascript ES6, 229 * 80% * 75% * 50% = 68.7 bytes
Test Input
I'm using the following test data:
var A1=[
  5,6,7,            // => 5-7     # (a) group pages
  2,3,              // => 2-3,5-7 # (b) must be properly sorted
  -9,-8,-7,         // => -10--8  # (c) allow negative numbers
  29,30,31,32,      // => 29-2    # (d) lower last digit implies increasing the 10s place
  9,10,11,12,       // => 9-11    # NOT 9-2
  36,37,38,39,40,41,42,43,44,45,46,47,
                    // => 36-47   # NOT 36-7
  99,100,101,102,   // => 99-102  # NOT 99-2
  109,110,111,112,  // => 109-2   # NOT 109-12
],
// more tests, not specified in the question
A2=[
  120,124,       // => 120,124 # (e) handle single pages
],
A3=[
  135,136,135    // => 135-6   # (f) handle duplicates
];

Basic: 229 bytes
This version satisfies the requirements of the question (a) with all bonuses (c,d,e), but hangs on single pages. It can also handle duplicates(f). It handles negative pages down to -10,000, which can be easily increased with (large) loss of speed.
F=(a)=>{var R=[],i=NaN,l,u;a.map(x=>R[1e4+x]=x);R.concat('').map(x=>(i!=i&&(l=x,u=l-1),i=0,u=(x+="")-u-1?l=console.log(l+'-'+(u>0?(l.length-u.length||(z=>{for(;l[i]==u[i];i++);})(),u.length-i-2||u-l>9||i++,u.slice(i)):u))||x:x))}
F(A1.concat(A3)) --> -9--7 2-3 5-7 9-12 29-2 36-47 99-102 109-2 135-136

(The output above shows spaces instead of actual newlines for brevity)
Single pages: 233 bytes
This slightly longer version additionally satisfies (e) and displays single pages as a range with equal lower and upper limits
G=(a)=>{var R=[],i=NaN,l,u;a.map(x=>R[1e4+x]=x);R.concat('').map(x=>(i!=i&&(l=x,u=l-1),i=0,u=(x+="")-u-1?l=console.log(l+'-'+(u-l&u>0?(l.length-u.length||(z=>{for(;l[i]==u[i];i++);})(),u.length-i-2||u-l>9||i++,u.slice(i)):u))||x:x))}
G(A1.concat(A2,A3)) --> -9--7 2-3 5-7 9-12 29-2 36-47 99-102 109-2 120-120 124-124

@Cyoce - Are you using an ES6-enabled javascript engine?

Oh, hmm, I have a bug, it doesn't actually handle 36-47 correctly. What's the proper procedure? Do I delete it and fix it, or just try to fix it (I may not have the time right now), or what?

Hmm, it just works in my Chrome. What gives?

And zocky, fix it when you can. It just won't count as valid until it's fixed, and as such can not be accepted until then (assuming yours is the fewest bytes).

Let us continue this discussion in chat.

Nice, it works!

Why 99-102  # NOT 99-2 ?

... and I think the single page should be managed, even if it's not in the test cases. The test cases or not meant to cover all possible cases.

Test [-3,-2,-1] fails

The longer version should manage single pages but fails on [1,3] (testing with FireFox) BUT works in Chrome

@edc: Why 99-102 # NOT 99-2  - I was extrapolating from 9-12, as included in the question.

OK, I now have a new version, and the one with bells and whistles is now significantly shorter. It now works for me on G([1,3]) in FireFox, but it still  ignores any ranges that end in -1. I'm at a loss there, for now.

I don't think the parentheses in F=(a)=> are required. Also, var shouldn't be necessary.

@zocky 9-12 was if you're not going for the bonuses. Since you are, it should be 99-2

Lua, 322*80%*75%*50% = 96.6 Bytes
Finally done with the 3 challenges, Scores under 100 bytes :D
Golfed
function f(l)table.sort(l)l[#l+1]=-13 a=l[1]t,s=a,"" for _,v in next,l do if v-t>1 or t-v>1 then s,p,r=s..a.."-",""..t,""..a r:gsub("%d",function(c)p=r:find(c)~=r:len()and p:gsub("^(-?)"..c,"%1")or p r=r:gsub("^"..c,"")end)p=t-a<10 and t%10<a%10 and p:gsub("^(%d)","")or p s,a,t=s..p..",",v,v else t=v end end return s end

Ungolfed
function f(l)
    table.sort(l)
    l[#l+1]=-13
    a=l[1]
    t,s=a,""
    for _,v in next,l
    do
        if v-t>1 or t-v>1
        then
            s,p,r=s..a.."-",""..t,""..a
            r:gsub("%d",function(c)
                p=r:find(c)~=#r and p:gsub("^(-?)"..c,"%1")or p
                r=r:gsub("^"..c,"")
            end)
            p=t-a<10 and t%10<a%10 and p:gsub("^(%d)","")or p
            s=s..p..","
            a,t=v,v
        else
            t=v
        end
    end
return s
end

You can test lua online, to see how it perform against the test cases, copy paste the function, followed by this code :
a={1,2,3,4,5}
b={3,4,5,9,10,11,12,13,14,15,16,17,18,19,20,21}
c={149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160}
d={-7,8,5,-6,-5,6,7}
print(f(a))
print(f(b))
print(f(c))
print(f(d))

Seems to fail if {9..21} is entered. Outputs 9-1.

@ICanHazHats Fixed, thanks for pointing it out :)

GAP, 355 Bytes *0.8*0.75*0.5 = 106.5
This satisfies all the bonuses. It cost me almost 100 extra bytes to make everything work nicely. This function only omits leading digits if the gap does not overflow the ones place once. For example 9 10 11 outputs 9-1 but 9 10 11 12 .. 20 21 outputs 9-21.
If GAP was a little less verbose, I could have gotten this pretty short (also could have saved many bytes if I didn't follow the exact syntax.) I'll probably try golfing this a bit harder tomorrow. See below for test cases.
g:=function(l)local n;if not l=[] then Sort(l);n:=1;while not l=[] do;if not IsSubset(l,[l[1]..l[1]+n]) then if not n=1 then if n-1>10-l[1] mod 10 and n-1<11 then Print(l[1],"-",(l[1]+n-1) mod 10);else Print(l[1],"-",l[1]+n-1);fi;else Print(l[1]);fi;Print(", ");SubtractSet(l,[l[1]..l[1]+n-1]);g(l);fi;n:=n+1;od;fi;Print("\b\b  ");end;

ungolfed:
g:=function(l)
    local n;
    if not l=[] then
        Sort(l);
        n:=1;
        while not l=[] do;
            if not IsSubset(l,[l[1]..l[1]+n]) then
                if not n=1 then
                    if n-1>10-l[1] mod 10 and n-1<11 then
                        Print(l[1],"-",(l[1]+n-1) mod 10);
                    else
                        Print(l[1],"-",l[1]+n-1);
                    fi;
                else
                    Print(l[1]);
                fi;
                Print(", ");
                SubtractSet(l,[l[1]..l[1]+n-1]);
                g(l);
            fi;
            n:=n+1;
        od;
    fi;
    Print("\b\b  ");
end;

Note that in GAP syntax, [a..b] is equivalent to [a,a+1,...,b]. I believe that these test cases demonstrate that this program meets all the requirements. If something is wrong, let me know.
gap> h([1..5]);
1-5
gap> h([3,4,5,9,10,11,12]);
3-5, 9-2
gap> h([149..160]);
149-160
gap> h([109..113]);
109-3
gap> h([19..29]);
19-9

gap> h([-1,-2,-3,-7,-20000,9,10,110101,110102]);
-20000, -7, -3--1, 9-10, 110101-110102

gap> h([10101,10102,10103,10,11,12,13,14,15,16,234,999,1000,1001,1002]);
10-16, 234, 999-2, 10101-10103

Java, 252 * 80% * 75% * 50% = 75.6 bytes
I've decided to go for a method (is much smaller in Java), here is the golfed version:
Golfed
int p,c,s;String m(int[]a){p=s=c=0;c--;String o="";Arrays.sort(a);for(int n:a){if(s==0)o+=s=n;else if(n-p==1)c++;else{o+=t()+", "+(s=n);c=-1;}p=n;}return o+t();}String t(){return c>=0?"-"+(""+p).substring((""+Math.abs(p)).length()-(""+c).length()):"";}

And here is the readable version:
int p, c, s;

String m(int[] a) {
    p = s = c = 0;
    c--;
    String o = "";
    Arrays.sort(a);
    for (int n : a) {
        if (s == 0)
            o += s = n;
        else if (n - p == 1)
            c++;
        else {
            o += t() + ", " + (s = n);
            c = -1;
        }
        p = n;
    }
    return o + t();
}

String t() {
    return c >= 0 ? "-" + ("" + p).substring(("" + Math.abs(p)).length() - ("" + c).length()) : "";
}

When tested these are the results:
import java.util.Arrays;
public class A {
    public static void main(String...s) {
        A a = new A();
        System.out.println(a.m(new int[] {1, 2, 3, 4, 5}));
        System.out.println(a.m(new int[] {3, 4, 5, 9, 10, 11, 12}));
        System.out.println(a.m(new int[] {149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160}));
        System.out.println(a.m(new int[] {109, 110, 111, 112, 113}));
        System.out.println(a.m(new int[] {19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}));
        System.out.println(a.m(new int[] {1,10,11,16}));
        System.out.println(a.m(new int[] {-3,-2,-1,0,1,2,3}));
        System.out.println(a.m(new int[] {-3,-2,-1}));
    }

    int p,c,s;String m(int[]a){p=s=c=0;c--;String o="";Arrays.sort(a);for(int n:a){if(s==0)o+=s=n;else if(n-p==1)c++;else{o+=t()+", "+(s=n);c=-1;}p=n;}return o+t();}String t(){return c>=0?"-"+(""+p).substring((""+Math.abs(p)).length()-(""+c).length()):"";}
}

Output:
1-5
3-5, 9-2
149-60
109-3
19-9
1, 10-1, 16
-3-3
-3--1

Update:
It can now handle negative numbers as well, adding to the bonus.

I'm no Java expert, but could you shorten it by changing p=s=c=0;c--; to p=s=0;c=-1; ?

I'm no Java expert, but could you shorten it by changing return c >= 0 ? "bla" : "" to return c < 0 ? "": "bla" ?

you could even do c=~(p=s=0) for style points.

Japt, 127 bytes * 80% * 75% * 50% = 38.1
Wow, that was one heck of a challenge to include all the bonuses. It could probably be made shorter.
D=[]N=Nn-;DpNr@Y-1¥Xg1 ?[Xg Y]:DpX ©[YY]}D;Ds1 £[BC]=Xms;B¥C?B:B+'-+CsBg ¦'-©Cl ¥Bl ©C¬r@B¯Z ¥C¯Z ªC-B§ApCl -Z ©ÂBsX <ÂCsX ?Z:X

Try it online!
How it works
The explanation is very rough; don't hesitate to ask any questions you might have.
/*    Setting up basic variables    */
                      // Implicit: A = 10, N = list of input numbers.
D=[],N=Nn-;           // D = empty array, N = N sorted by subtraction.

/*    Finding ranges of page numbers    */
Dp                    // Push into D the result of
NrXYZ{                // reducing each previous value X and item Y in N by this function,
}[];                  // starting with an empty array:
 Y-1==Xg1 ?           //  If Y is 1 more than the second item of X,
 [Xg Y]:              //   return [X[0], Y].
 DpX &&[YY]           //  Otherwise, push X into D and return [Y, Y].

/*    Formatting result    */
Ds1 mXYZ{             // Take the first item off of D and map each item X by this function:
 [BC]=Xms;            //  Set B and C to the first to items in X as strings.
 B==C?B               //  If B is the same as C, return B.
 :B+'-+Cs             //  Otherwise, return B + a hyphen + C.slice(
  Bg !='-&&           //   If B[0] is not a hyphen (B is not negative), AND
  Cl ==Bl &&          //   B and C are the same length,

  /*    Cutting off unnecessary digits    */
  Cq r                //    then C split into digits, reduced with
  rXYZ{               //    each previous value X, item Y, and index Z mapped by this function:
   Bs0,Z ==Cs0,Z ||   //     If B.slice(0,Z) equals C.slice(0,Z), OR
   C-B<=ApCl -Z       //     C - B <= 10 to the power of (C.length - Z);
   &&~~BsX <~~CsX     //     AND B.slice(X) is a smaller number than C.slice(X),
   ?Z:X               //     then Z; otherwise, X.
                      //   Otherwise, 0.

R, 167 bytes x 80% x 75% x 50% -> 50.1
s=sort(scan(se=","));r=c();while(length(s)){w=s==1:length(s)+s[1]-1;x=s[w];s=s[!w];z=tail(x,1);r=c(r,paste0(x[1],"-",ifelse(z-x[1]<=10,z%%10,z%%100)))};cat(r,sep=", ")

Indented, with new lines:
s=sort(scan(se=","))
r=c()
while(length(s)){
w=s==1:length(s)+s[1]-1
x=s[w]
s=s[!w]
z=tail(x,1)
r=c(r, paste0(x[1],"-", ifelse(z-x[1]<=10,
                               z%%10,
                               z%%100)))}
cat(r,sep=", ")

Test cases:
> s=sort(scan(se=","));r=c();while(length(s)){w=s==1:length(s)+s[1]-1;x=s[w];s=s[!w];r=c(r,paste0(x[1],"-",ifelse(tail(x,1)-x[1]<=10,tail(x,1)%%10,tail(x,1)%%100)))};cat(r,sep=", ")
1: 3, 4, 5, 9, 10, 11, 12
8:
Read 7 items
3-5, 9-2
> s=sort(scan(se=","));r=c();while(length(s)){w=s==1:length(s)+s[1]-1;x=s[w];s=s[!w];r=c(r,paste0(x[1],"-",ifelse(tail(x,1)-x[1]<=10,tail(x,1)%%10,tail(x,1)%%100)))};cat(r,sep=", ")
1: 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160
13:
Read 12 items
149-60

It works for the -50% bonus:
> s=sort(scan(se=","));r=c();while(length(s)){w=s==1:length(s)+s[1]-1;x=s[w];s=s[!w];r=c(r,paste0(x[1],"-",ifelse(tail(x,1)-x[1]<=10,tail(x,1)%%10,tail(x,1)%%100)))};cat(r,sep=", ")
1: 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29
12:
Read 11 items
19-9
> s=sort(scan(se=","));r=c();while(length(s)){w=s==1:length(s)+s[1]-1;x=s[w];s=s[!w];r=c(r,paste0(x[1],"-",ifelse(tail(x,1)-x[1]<=10,tail(x,1)%%10,tail(x,1)%%100)))};cat(r,sep=", ")
1: 109, 110, 111, 112, 113
6:
Read 5 items
109-3

It accepts unsorted input:
> s=sort(scan(se=","));r=c();while(length(s)){w=s==1:length(s)+s[1]-1;x=s[w];s=s[!w];r=c(r,paste0(x[1],"-",ifelse(tail(x,1)-x[1]<=10,tail(x,1)%%10,tail(x,1)%%100)))};cat(r,sep=", ")
1: 114, 109, 110, 111, 112, 113
7:
Read 6 items
109-4

It accepts negative numbers:
> s=sort(scan(se=","));r=c();while(length(s)){w=s==1:length(s)+s[1]-1;x=s[w];s=s[!w];r=c(r,paste0(x[1],"-",ifelse(tail(x,1)-x[1]<=10,tail(x,1)%%10,tail(x,1)%%100)))};cat(r,sep=", ")
1: -1,0,1,2
4:
Read 3 items
-1-2

sh, 135 * .8 * .75 * .5 = 40.5
tr , \\n|sort -n|awk -vORS="" '$1-o>1||!c{print p c$1;s=$1}{o=$1;c=", ";p=""}o>s{p="-"substr(o,length(o)-length(o-s-1)+1)}END{print p}'

shell script

tr , \\n|           # comma separated -> newline separated
sort -n|            # sort
awk -vORS=""        # suppress automatic newlines in output

awk script

# on step > 1 or first run, end the current sequence and start a new one.
# on first run, p and c are empty strings.
$1-o>1||!c
    {print p c$1;s=$1}

# old = current, c = ", " except for first run, clear end string.
    {o=$1;c=", ";p=""}

# if the sequence is not a single number, its end is denoted by "-o".
# print only the last n digits of o.
o>s
    {p="-"substr(o,length(o)-length(o-s-1)+1)}

# end the current sequence without starting a new one.
END
    {print p}'

where s is the start of the current sequence and o is the previous input value.

I like it, but it doesn't get the -25% bonus currently. substr() is chopping off minus signs and significant digits.

@ezrast This is actually correct behaviour in terms of the -50% bonus: -31, -30, -29, -28 increases in the 10's place from -3 to -2 and shall therefore be condensed to -31-8. I also see the ambiguity it creates, but that's what is asked for.


text:
King-Pen! (Dots and Boxes)
This is a king of the hill challenge for Dots and Boxes (aka Pen the Pig). The game is simple, on your turn just draw a line on an empty fence. Every time you complete a square you get a point. Also, since we are playing by championship rules, if you complete at least one square on your turn you get an extra turn. This is a round robin tournament, where each bot plays each other bot twice 12 times on a 9x9 grid. Check out this match between two heavyweight titans, where ChainCollector makes mince meat of reigning co-champion Asdf:

Rules

0.5 second time limit per move.
No interfering with other bots.
Use PigPen.random() and PigPen.random(int) for randomness.
No writing to files.
Bot and all its persistent data will be reset every time opponent changes (every 12 rounds).

Bots
Every bot extends Player.java:
package pigpen;

public abstract class Player {

public abstract int[] pick(Board board, int id, int round);

}

Board is the game board, which mainly serves to give you access to Pen classes, and id is your playerID (tells you if you're first or second), round tells you which round your playing against the same opponent (1 or 2). The return value is an int[], where the first element is the penID (1-indexed), and the second element is the fenceID (0-indexed). See Pen.pick(int) for an easy way to generate this return value. See the Github page for example players and JavaDoc. Since we are only using a square grid ignore any functions and fields related to hexagons.
How to Run

Download Source from Github.
Write your controller bot (make sure to include package pigpen.players) and put it in the src/ folder;
Compile with javac -cp src/* -d . src/*.java. Run with java pigpen.Tournament 4 9 9 false (the last two numbers can be changed to adjust grid size. The last variable should only be set to true if you wish to use the pp_record software.)

Scores

ChainCollector: 72
Asdf: 57
Lazybones: 51
Finisher: 36
=LinearPlayer: 18
=BackwardPlayer: 18
RandomPlayer: 0

See Also:

Dots and Boxes fastest code
Dots and Boxes Wikipedia page

Note: this game is a competitive challenge and not easily solvable, due to giving players an extra turn for completing a box.
Thanks to Nathan Merrill and Darrel Hoffman for consulting on this challenge!
Updates:

Added a moves(int player) method to the Board class to get a list of every move a player has made.

Indefinite Bounty (100 Rep):
First person to post a solution that wins every round, and uses strategy (adjusting play based on observing how the opponent plays).

GOODNESS. Finisher is waaayyyy OP! :P

@El'endiaStarman Lol, all he does is finish a Pen with one fence available, or otherwise picks a Pen with the most fences remaining. RandomPlayer is just random.

Yeah, I know. It's just that the final score is 79-2 and RandomPlayer only got those last two boxes because it had to. :P

Hello! I want to make my own bot, but I have a question. will Pen.BOTTOM at row 0 col 0 return the same values as Pen.TOP at row 1 col 0?

@tusk Yes, it does

Lazybones
This bot is lazy. He picks a random spot and direction and continues to build in that direction without moving too much. There are only 2 cases where he does something different:

"make money" by closing a peg with only 1 remaining fence
choose a new spot and direction if placing the fence is not possible or would allow the other bot to "make money"

package pigpen.players;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import pigpen.Board;
import pigpen.Pen;
import pigpen.PigPen;
import pigpen.Player;

public class Lazybones extends Player {
    private static class Fence {
        private static boolean isOk(Board board, boolean vertical, int row, int col) {
            if (vertical) {
                Pen left = board.getPenAt(row, col - 1);
                Pen right = board.getPenAt(row, col);
                if (left.id() < 0 && right.id() < 0 ||
                        left.fences()[Pen.RIGHT] > 0 ||
                        right.fences()[Pen.LEFT] > 0 ||
                        left.remaining() == 2 ||
                        right.remaining() == 2) {
                    return false;
                }
            } else {
                Pen top = board.getPenAt(row - 1, col);
                Pen bottom = board.getPenAt(row, col);
                if (top.id() < 0 && bottom.id() < 0 ||
                        top.fences()[Pen.BOTTOM] > 0 ||
                        bottom.fences()[Pen.TOP] > 0 ||
                        top.remaining() == 2 ||
                        bottom.remaining() == 2) {
                    return false;
                }
            }
            return true;
        }

        private static Fence pickRandom(Board board) {
            List<Fence> ok = new ArrayList<>();
            List<Fence> notOk = new ArrayList<>();
            for (int row = 0; row < board.rows; row ++) {
                for (int col = 0; col < board.cols; col ++) {
                    (isOk(board, false, row, col) ? ok : notOk)
                            .add(new Fence(false, row, col));
                    (isOk(board, true, row, col) ? ok : notOk)
                            .add(new Fence(true, row, col));
                }
                (isOk(board, true, row, board.cols) ? ok : notOk)
                        .add(new Fence(true, row, board.cols));
            }
            for (int col = 0; col < board.cols; col ++) {
                (isOk(board, false, board.rows, col) ? ok : notOk)
                        .add(new Fence(false, board.rows, col));
            }
            if (ok.isEmpty()) {
                return notOk.get(PigPen.random(notOk.size()));
            } else {
                return ok.get(PigPen.random(ok.size()));
            }
        }

        private final boolean vertical;
        private final int row;
        private final int col;

        public Fence(boolean vertical, int row, int col) {
            super();
            this.vertical = vertical;
            this.row = row;
            this.col = col;
        }

        private Fence next(Board board, boolean negative) {
            int newRow = vertical ? (negative ? row - 1 : row + 1) : row;
            int newCol = vertical ? col : (negative ? col - 1 : col + 1);
            if (isOk(board, vertical, newRow, newCol)) {
                return new Fence(vertical, newRow, newCol);
            } else {
                return null;
            }
        }

        private int[] getResult(Board board) {
            if (vertical) {
                if (col < board.cols) {
                    return board.getPenAt(row, col).pick(Pen.LEFT);
                } else {
                    return board.getPenAt(row, col - 1).pick(Pen.RIGHT);
                }
            } else {
                if (row < board.rows) {
                    return board.getPenAt(row, col).pick(Pen.TOP);
                } else {
                    return board.getPenAt(row - 1, col).pick(Pen.BOTTOM);
                }
            }
        }
    }

    private Fence lastFence = null;
    private boolean negative = false;

    @Override
    public int[] pick(Board board, int id, int round) {
        List<Pen> money = board.getList().stream()
                .filter(p -> p.remaining() == 1).collect(Collectors.toList());
        if (!money.isEmpty()) {
            return money.get(PigPen.random(money.size())).pick(Pen.TOP);
        }
        if (lastFence != null) {
            lastFence = lastFence.next(board, negative);
        }
        if (lastFence == null) {
            lastFence = Fence.pickRandom(board);
            negative = PigPen.random(2) == 0;
        }
        return lastFence.getResult(board);
    }
}

Wow, nice job! LazyBones owns finisher (see new animation).

By the way, just so everyone knows, another way to get the Pen to the left of a given pen is pen.n(Pen.LEFT) (neighbor function).

Also, I think it's unnecessary when you check the bottom fence of a Pen and the top fence of the one below it, they are guaranteed to have the same value!

The pick() method now has an int round parameter at the end, so if you could please add that.

I have to check both fences, because any of the pen objects can be outside of the board (id == -1). For the same reason I can't use the neighbor function.

ChainCollector
This bot likes chains1. He wants as much of them as possible. Sometimes he even sacrifices a small part of a chain to win a bigger one.
[1] A chain consists of pens connected by open fences, where each pen has 1 or 2 open fences. If a single pen belonging to the chain can be finished, then because of the championship rule the whole chain can be finished as well.
package pigpen.players;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.TreeMap;

import pigpen.Board;
import pigpen.Pen;
import pigpen.Player;

public class ChainCollector extends Player {
    private enum Direction {
        TOP, RIGHT, BOTTOM, LEFT;

        public Direction opposite() {
            return values()[(ordinal() + 2) % 4];
        }
    }

    private enum ChainEndType {
        OPEN, CLOSED, LOOP
    }

    private static class PenEx {
        private final int id;
        private final List<Fence> openFences = new ArrayList<>();
        private boolean used = false;

        public PenEx(int id) {
            super();
            this.id = id;
        }

        public void addOpenFence(Direction direction, PenEx child) {
            openFences.add(new Fence(this, direction, child));
            if (child != null) {
                child.openFences.add(new Fence(child, direction.opposite(), this));
            }
        }
    }

    private static class Fence {
        public final PenEx parent;
        public final Direction direction;
        public final PenEx child;

        public Fence(PenEx parent, Direction direction, PenEx child) {
            super();
            this.parent = parent;
            this.direction = direction;
            this.child = child;
        }

        public int[] getMove() {
            if (parent == null) {
                return new int[] { child.id, direction.opposite().ordinal() };
            } else {
                return new int[] { parent.id, direction.ordinal() };
            }
        }
    }

    private static class Moves {
        private final TreeMap<Integer, List<Fence>> map = new TreeMap<>();

        public void add(int score, Fence move) {
            List<Fence> list = map.get(score);
            if (list == null) {
                list = new ArrayList<>();
                map.put(score, list);
            }
            list.add(move);
        }

        public boolean isEmpty() {
            return map.isEmpty();
        }

        public boolean hasExactlyOne() {
            return map.size() == 1 && map.firstEntry().getValue().size() == 1;
        }

        public int getLowestScore() {
            return map.firstKey();
        }

        public int[] getLowMove() {
            return map.firstEntry().getValue().get(0).getMove();
        }

        public int[] getHighMove() {
            return map.lastEntry().getValue().get(0).getMove();
        }
    }

    private static class BoardEx {
        private final List<PenEx> pens = new ArrayList<>();
        private final Moves neutralMoves = new Moves();
        private final Moves finisherMoves = new Moves();
        private final Moves safeFinisherMoves = new Moves();
        private final Moves sacrificeMoves = new Moves();
        private final Moves badMoves = new Moves();

        public BoardEx(Board board) {
            super();
            PenEx[][] tmp = new PenEx[board.rows][board.cols];
            for (int row = 0; row < board.rows; ++row) {
                for (int col = 0; col < board.cols; ++col) {
                    Pen pen = board.getPenAt(row, col);
                    int[] fences = pen.fences();
                    PenEx penEx = new PenEx(pen.id());
                    tmp[row][col] = penEx;
                    pens.add(penEx);
                    if (fences[Pen.TOP] == 0) {
                        penEx.addOpenFence(Direction.TOP, row == 0 ? null : tmp[row - 1][col]);
                    }
                    if (row == board.rows - 1 && fences[Pen.BOTTOM] == 0) {
                        penEx.addOpenFence(Direction.BOTTOM, null);
                    }
                    if (fences[Pen.LEFT] == 0) {
                        penEx.addOpenFence(Direction.LEFT, col == 0 ? null : tmp[row][col - 1]);
                    }
                    if (col == board.cols - 1 && fences[Pen.RIGHT] == 0) {
                        penEx.addOpenFence(Direction.RIGHT, null);
                    }
                }
            }
        }

        private ChainEndType followChain(Fence begin, List<Fence> result) {
            Fence current = begin;
            for (;;) {
                current.parent.used = true;
                result.add(current);
                if (current.child == null) {
                    return ChainEndType.OPEN;
                }
                List<Fence> childFences = current.child.openFences;
                switch (childFences.size()) {
                    case 1:
                        current.child.used = true;
                        return ChainEndType.CLOSED;
                    case 2:
                        if (current.child == begin.parent) {
                            return ChainEndType.LOOP;
                        } else {
                            current = current.direction.opposite() == childFences.get(0).direction ?
                                    childFences.get(1) : childFences.get(0);
                        }
                        break;
                    case 3:
                    case 4:
                        return ChainEndType.OPEN;
                    default:
                        throw new IllegalStateException();
                }
            }
        }

        public void findChains() {
            for (PenEx pen : pens) {
                if (!pen.used && pen.openFences.size() > 0) {
                    if (pen.openFences.size() < 3) {
                        List<Fence> fences = new ArrayList<>();
                        ChainEndType type1 = pen.openFences.size() == 1 ?
                                ChainEndType.CLOSED : followChain(pen.openFences.get(1), fences);
                        if (type1 == ChainEndType.LOOP) {
                            badMoves.add(fences.size(), fences.get(0));
                        } else {
                            Collections.reverse(fences);
                            ChainEndType type2 = followChain(pen.openFences.get(0), fences);
                            if (type1 == ChainEndType.OPEN && type2 == ChainEndType.CLOSED) {
                                type1 = ChainEndType.CLOSED;
                                type2 = ChainEndType.OPEN;
                                Collections.reverse(fences);
                            }
                            if (type1 == ChainEndType.OPEN) {
                                badMoves.add(fences.size() - 1, fences.get(fences.size() / 2));
                            } else if (type2 == ChainEndType.CLOSED) {
                                finisherMoves.add(fences.size() + 1, fences.get(0));
                                if (fences.size() == 3) {
                                    sacrificeMoves.add(fences.size() + 1, fences.get(1));
                                } else {
                                    safeFinisherMoves.add(fences.size() + 1, fences.get(0));
                                }

                            } else {
                                finisherMoves.add(fences.size(), fences.get(0));
                                if (fences.size() == 2) {
                                    sacrificeMoves.add(fences.size(), fences.get(1));
                                } else {
                                    safeFinisherMoves.add(fences.size(), fences.get(0));
                                }
                            }
                        }
                    } else {
                        pen.used = true;
                        for (Fence fence : pen.openFences) {
                            if (fence.child == null || fence.child.openFences.size() > 2) {
                                neutralMoves.add(fence.child == null ? 0 : fence.child.openFences.size(), fence);
                            }
                        }
                    }
                }
            }
        }

        public int[] bestMove() {
            if (!neutralMoves.isEmpty()) {
                if (!finisherMoves.isEmpty()) {
                    return finisherMoves.getHighMove();
                }
                return neutralMoves.getHighMove();
            }
            if (!safeFinisherMoves.isEmpty()) {
                return safeFinisherMoves.getHighMove();
            }
            if (badMoves.isEmpty() && !finisherMoves.isEmpty()) {
                return finisherMoves.getHighMove();
            }
            if (!sacrificeMoves.isEmpty()) {
                if (sacrificeMoves.hasExactlyOne()) {
                    if (badMoves.getLowestScore() - sacrificeMoves.getLowestScore() >= 2) {
                        return sacrificeMoves.getLowMove();
                    } else {
                        return finisherMoves.getHighMove();
                    }
                } else {
                    return finisherMoves.getHighMove();
                }
            }
            if (!badMoves.isEmpty()) {
                return badMoves.getLowMove();
            }
            return null;
        }
    }

    @Override
    public int[] pick(Board board, int id, int round) {
        BoardEx boardEx = new BoardEx(board);
        boardEx.findChains();
        return boardEx.bestMove();
    }
}

Wow, thank you for your entry. I am humbled that someone has put in so much time into a project I created. I think the introduction of this bot has affected the random number generation, such that Asdf now beats Lazybones both times by a slight margin.

Well, the idea for the bot looked pretty simple before I started, and then I wanted to finish it. ;) With randomness involved you should probably let the bots play more than 2 games to get more accurate results.

Good thought. I increased it to 12 rounds per matchup, and now, as you can see, Asdf has a slight edge. Even at 100 rounds, it only wins 13 more games than Lazybones.

Finisher
package pigpen.players;

import pigpen.*;

import java.util.*;

/**
 * Picks a Pen with only one fence remaining.
 * Otherwise picks one with the most fences remaining
 */
public class Finisher extends Player implements Comparator<Pen> {

  public int[] pick(Board board, int id) {
     return Collections.max(board.getList(),this).pick(Pen.TOP);

  }

  @Override
  public int compare(Pen p1, Pen p2) {
    //1 remaining is best, all remaining is second.
    int r1 = p1.remaining();
    int r2 = p2.remaining();
    if(r1 == 1) r1 = 7;
    if(r2 == 1) r2 = 7;
    return Integer.compare(r1,r2);
 }

}

Uses a Comparator to pick the Pen with the most available fences, but gives priority to Pen's with only 1 fence available. (7 is used rather than 5 to allow this code to work in hexagon mode as well)

Asdf
Assigns a score to each fence and then picks the best out of them. For example: A pen with one open fence has a score of 10, while a pen with 2 open fences has a score of -8.
It seems like Lazybones uses a similar strategy, because it ties with this bot.
package pigpen.players;

import java.util.*;
import pigpen.*;

public class Asdf extends Player {
    private final List<Score> scores = new ArrayList<>();

    @Override
    public int[] pick(Board board, int id, int round) {
        scores.clear();
        List<Pen> pens = board.getList();

        pens.stream().filter(x -> !x.closed()).forEach((Pen p) -> evaluate(p));
        Optional<Score> best = scores.stream().max(Comparator.comparingInt(p -> p.points));

        if (best.isPresent()) {
            Score score = best.get();
            return score.pen.pick(score.fence);
        }
        return null;
    }

    private void evaluate(Pen pen) {
        int[] fences = pen.fences();
        for (int i = 0; i < fences.length; i++) {
            if (fences[i] == 0) {
                int points = getPoints(pen);
                Pen neighbour = pen.n(i);
                if (neighbour.id() != -1) {
                    points += getPoints(neighbour);
                }
                scores.add(new Score(pen, i, points));
            }
        }
    }

    private int getPoints(Pen pen) {
        switch (pen.remaining()) {
            case 1: return 10;
            case 2: return -1;
            case 3: return 1;
        }
        return 0;
    }

    class Score {
        private Pen pen;
        private int fence;
        private int points;

        Score(Pen pen, int fence, int points) {
            this.pen = pen;
            this.fence = fence;
            this.points = points;
        }
    }
}

Here are the scores. It's interesting that whoever goes second gets twice as many points. Asdf vs. Lazybones: 27 - 54;
Lazybones vs. Asdf: 27 - 54

@geokavel Yes, because then the bots are forced to do a "bad turn", so the opponent can close a pen.

Is this the best possible algorithm, then?

@justhalf It's not, because people play this game in championships. I think these algorithms can definitely be expanded on. See the links I provided for more info.

LinearPlayer
package pigpen.players;

import pigpen.*;

/**
 * Picks the first available fence in the first available Pen
 */
public class LinearPlayer extends Player {

@Override
public int[] pick(Board board, int id) {
    for(int p = 1;p<=board.size;p++) {
        Pen pen = board.get(p);
            if(!pen.closed()) {
                int[] fences = pen.fences();
                    for(int i =0;i<fences.length;i++) {
                        if(fences[i] == 0) {
                            return new int[]{pen.id(),i};
                        }
                    }
                }
        }
    return new int[]{1,0};
    }
}

The easiest way to write this bot is actually return null, because an invalid entry will automatically select the first available fence. This code does not use any shortcut methods and manually generates the return value.

BackwardPlayer
package pigpen.players;

import pigpen.*;

/**
 * Picks the first available fence in the last available Pen
 */
 public class BackwardPlayer extends Player {

public int[] pick(Board board, int id) {
    for(int i = board.size;i>0;i--) {
        Pen p = board.get(i);
        if(!p.closed()) {
            return p.pick(Pen.TOP);
        }
    }
    return new int[] {1,0};
}
}

This code uses the shortcut method Pen.pick(int) to generate the return value. If the top fence is unavailable, it will pick the closest available fence going clockwise.

RandomPlayer
package pigpen.players;

import pigpen.*;

/**
 * Picks the first available fence in a random Pen
 */
public class RandomPlayer extends Player {
    public int[] pick(Board board, int id) {
        int pen = PigPen.random(board.size)+1;
        return board.get(pen).pick(Pen.TOP);
    }
}

Same idea as BackwardPlayer, but randomly selects a pen. Note the +1 because Pen's are 1-indexed.

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

sort: votes


text:
Find the nth Fibohexaprime
The challenge this time is to find the nth Fibohexaprime. The definition of a Fibohexaprime is as following:
We first observe a list with Fibonacci numbers:
N  | Fibonacci number
1  | 1
2  | 1
3  | 2
4  | 3
5  | 5
6  | 8
7  | 13
8  | 21
9  | 34
10 | 55
11 | 89
12 | 144
13 | 233
14 | 377
15 | 610
16 | 987
17 | 1597

After that, we convert the numbers to hexadecimal:
N  | Fib  | Hex
1  | 1    | 1
2  | 1    | 1
3  | 2    | 2
4  | 3    | 3
5  | 5    | 5
6  | 8    | 8
7  | 13   | D
8  | 21   | 15
9  | 34   | 22
10 | 55   | 37
11 | 89   | 59
12 | 144  | 90
13 | 233  | E9
14 | 377  | 179
15 | 610  | 262
16 | 987  | 3DB
17 | 1597 | 63D

From the hexadecimal numbers, we filter out the letters. All we are left with are numbers. We need to check if these numbers are prime:
hex |  filtered |  is prime? |  N =
1   >  1        >  false
1   >  1        >  false
2   >  2        >  true         1
3   >  3        >  true         2
5   >  5        >  true         3
8   >  8        >  false
D   >  0        >  false
15  >  15       >  false
22  >  22       >  false
37  >  37       >  true         4
59  >  59       >  true         5
90  >  90       >  false
E9  >  9        >  false
179 >  179      >  true         6
262 >  262      >  false
3DB >  3        >  true         7
63D >  63       >  false

If the filtered number is a prime, we call this a Fibohexaprime. You can see that for N = 7, the related fibonacci number is 987.
The task is simple, when given an input using STDIN or an acceptable alternative, write a program or a function which outputs the nth Fibohexaprime using STDOUT or an acceptable alternative.
Test cases
Input - Output
1     - 2
2     - 3
3     - 5
4     - 55
5     - 89
6     - 377
7     - 987
8     - 28657
9     - 75025
10    - 121393
11    - 317811
12    - 5702887
13    - 9227465
14    - 39088169
15    - 102334155
16    - 32951280099
17    - 4052739537881
18    - 806515533049393
19    - 7540113804746346429

The rules:

Given an integer between 1 and 19 (the values above 20 exceed the max value for a 64-bit signed integer), output the corresponding value.
You may write a function or a program.
This is code-golf, so the submission with the least amount of bytes wins!

The way it's worded, it sounds like functions must also read from STDIN and write to STDOUT. Is that correct? Typically we allow functions to accept arguments and return values as convenient.

@AlexA. Both are acceptable alternatives. Reading from STDIN and using STDOUT is not mandatory.

Pyth, 27 bytes
Leu,eGsGbU2ye.fq1lPs-.HyZGQ

Demonstration
y computes the nth Fibonacci number. A .f loop finds the fibohexaprime according to the input.

MATL, 28 bytes
This uses MATL version 1.0.0, which was published in Esolangs on December 12, earlier than this challenge.
1Hi:"`tb+t16YAt58<)YtZp~]]1$

Example
>> matl 1Hi:"`tb+t16YAt58<)YtZp~]]1$
> 10
121393

Explanation
The code is similar to that in Martin Büttner's answer.
1           % number literal
H           % paste from clipboard H. Initial contents: 2
i:          % vector of equally spaced values from 1 to input value
"           % for
  `         % do...while
    t       % duplicate
    b       % bubble up element in stack
    +       % addition
    t       % duplicate
    16YA    % convert integer to string representation in base 16
    t       % duplicate
    58      % number literal: first ASCII code after '9'
    <       % is less than? (element-wise)
    )       % reference () indexing with logical index from previous comparison
    Yt      % convert string to number
    Zp      % true for prime numbers
    ~       % logical 'not'
  ]         % end
]           % end
1$          % input specification for final implicit display function

The world's first MATL answer! Good job, Luis!

Hurray for MATL!  Welcome to the world of code golfing!

CJam, 28 bytes
TXri{{_@+_Gb{A<},Abmp!}g}*p;

Test it here.
Explanation
TX        e# Push 0 and 1 to initialise Fibonacci computation.
ri        e# Read input and convert to integer N.
{         e# Run this block N times...
  {       e#   While the condition on top of the stack is truthy...
    _@+   e#     Compute next Fibonacci number (dropping the second-to-last one).
    _Gb   e#     Duplicate and convert to base 16.
    {A<}, e#     Keep only digits less than 10.
    Ab    e#     Convert from base 10.
    mp!   e#     Check that it's not a prime.
  }g
}*
p;        e# Print the last number we found and discard the one before.

Perl 6, 62 bytes
My first pass of just get it to work was:
{(grep *[1].is-prime,map {$_,+[~] .base(16)~~m:g/\d/},(1,1,*+*...*))[$_-1;0]} # 77

By combining the grep and the map, I can remove 10 bytes
{(map {$_ if is-prime [~] .base(16)~~m:g/\d/},(1,1,*+*...*))[$_-1]} # 67

If I use grep instead of map, I save 5 more bytes:
{(grep {is-prime [~] .base(16)~~m:g/\d/},(1,1,*+*...*))[$_-1]} # 62

usage:
# give it a name
my &code = {...}

say code $_ for 1..^20;

2
3
5
55
89
377
987
28657
75025
121393
317811
5702887
9227465
39088169
102334155
32951280099
4052739537881
806515533049393
7540113804746346429

Julia, 123 bytes
n->(a=[];i=1;while endof(a)<n b=([1 1;1 0]^i)[1];(s=filter(isdigit,hex(b)))>""&&isprime(parse(s))&&push!(a,b);i+=1end;a[n])

This is an anonymous function that accepts an integer and returns an integer. To call it, give it a name, e.g. f=n->....
Ungolfed:
function f(n::Integer)
    # Initialize an array and an index
    a = []
    i = 1

    # Loop while we've generated fewer than n fibohexaprimes
    while endof(a) < n
        # Get the ith Fibonacci number
        b = ([1 1; 1 0]^i)[1]

        # Filter the hexadecimal representation to digits only
        s = filter(isdigit, hex(b))

        # If there are digits to parse, parse them into an
        # integer, check primality, and push the Fibonacci
        # number if prime
        s > "" && isprime(parse(s)) && push!(a, b)

        # Next
        i += 1
    end

    # Return the last generated
    return a[n]
end

C, 186 183 bytes
#include<stddef.h>
size_t a,b,c,d,m,x;size_t F(n){a=0,b=1;while(n){x=b;b+=a;a=x;c=0,m=1;while(x)d=x%16,m*=d<10?c+=m*d,10:1,x/=16;d=c>1;x=2;while(x<c)if(c%x++==0)d=0;d&&--n;}return a;}

The primality test is very inefficient, so the computation will struggle a bit for n > 16 and become painfully long for n = 19. Nevertheless it works and gives the expected results.
The code assumes that size_t is a 64bit type, which is true for both 64bit Linux and Windows.

Bonus: unfortunately we are required to use 64bit types, which lead to an overhead of 33 bytes. The following version works for n <= 15 using int and is 150 byte long:
a,b,c,d,m,x;F(n){a=0,b=1;while(n){x=b;b+=a;a=x;c=0,m=1;while(x)d=x%16,m*=d<10?c+=m*d,10:1,x/=16;d=c>1;x=2;while(x<c)if(c%x++==0)d=0;d&&--n;}return a;}

Test main:
#include <stdio.h>

int main() {
  printf("Input - Output\n");
  for (int i = 1; i < 20; ++i) {
    printf("%2d    - %ld\n", i, F(i));
  }
}

Could you save a bit by using size_t and dropping the include? It's implementation-specific, but seems to be 64-bit in both 64-bit Linux and Windows gcc (and since when did we care about portability in codegolf?). (side note: %ld is not 64-bit in 64-bit Windows; needs %lld)

@Bob I thought about it, but size_t is not a builtin, it's defined in stddef.h (which in turn is directly or indirectly included by virtually any other header). One way or the other, I need an #include. I can still save 2 bytes by using size_t instead of uint64_t, though :)

Also thanks for the lld bit, I didn't get the chance to test it on Windows (but portability doesn't matter, right?)

Hm, it must've come from stdio.h while I was testing. In any case - you could still save a couple by including math.h instead of stddef.h.

math.h doesn't do the trick for me (GCC 4.9 with GNU libc)

Hm, that's odd. I could've sworn TDM-GCC worked. Maybe some quirk with the MinGW/VC++ libraries. Anyway, time.h seems to work on ideone, albeit with sizeof(size_t) == 4.

Just checked. Both math.h and time.h work in gcc version 5.1.0 (tdm64-1). It takes them from x86_64-w64-mingw32, where math.h includes crtdefs.h where __MINGW_EXTENSION typedef unsigned __int64 size_t; happens. So if you're willing to accept a Works on My Machine, that saves you two characters! :P

Mathematica 111 bytes
There may still be room for additional golfing.
t=Table[Fibonacci@k,{k,1600}];f@n_:=PrimeQ@FromDigits[Select[n~IntegerDigits~16,#<10&]];
g@k_:=Select[t,f][[k]]

g[7]

987

g[19]

7540113804746346429

GAP, 204 Bytes
This answer is pretty unremarkable, except that GAP is cool enough to be able to find the next couple fibohexaprimes (and cooler still, it finds these in milliseconds with the given code).
gap>f(20);
31940434634990099905
gap> f(21);
12776523572924732586037033894655031898659556447352249
gap> f(22);
971183874599339129547649988289594072811608739584170445
gap> f(23);
1324695516964754142521850507284930515811378128425638237225
gap> f(24);
187341518601536966291015050946540312701895836604078191803255601777

Note that f(24) is between 2^216 and 2^217.
Here is the code:
f:=function(n)local c,i,x;c:=1;i:=0;while c<=n do x:=HexStringInt(Fibonacci(i));RemoveCharacters(x,"ABCDEFGHIJKLMNOPQRSTUVWXYZ");x:=Int(x);if IsPrime(x) then c:=c+1;fi;i:=i+1;od;Print(Fibonacci(i-1));end;

There's probably still some golfing that could be done. I think the implementation is pretty straightforward.
Ungolfed:
f:=function(n)
    local counter,i,x;
    counter:=1;i:=0;
    while counter<=n do
        x:=HexStringInt(Fibonacci(i));
        RemoveCharacters(x,"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
        x:=Int(x);
        if IsPrime(x) then
            counter:=counter+1;
        fi;
        i:=i+1;
    od;
    Print(Fibonacci(i-1));
end;

Python 2, 127 bytes
N=input();a,b=0,1
while N:a,b=b,a+b;t=int(''.join(c for c in hex(b)if ord(c)<65));N-=(t>1)*all(t%x for x in range(2,t))
print b

The algorithm could be a lot more efficient. In particular, the primality check (t>1)*all(t%x for x in range(2,t)) checks potential factors all the way up to t-1, when really it would only have to check up to the floor of the square root. Since range stores an entire list in memory in Python 2 , this leads to a MemoryError at N=17 (on my machine using default settings).

Ruby, 160 bytes
->i{t,o,k=[],[],0;f=->n{t[n]||=n<3?1:f[n-2]+f[n-1]};(r=('%x'%f[k]).scan(/\d/).join.to_i;(r>1&&(r==2||(2...r).none?{|j|r%j==0}))&&o<<r;k+=1)while !o[i-1];t[k-1]}

Ungolfed:
-> i {
  t, o, k = [], [], 0
  f = -> n {
    t[n] ||= n < 3 ? 1 : f[n-2] + f[n-1]
  }
  while !o[i-1] do
    r=('%x'%f[k]).scan(/\d/).join.to_i
    o << r if (r > 1 && (r == 2 || (2...r).none?{|j| r%j == 0 }))
    k+=1
  end
  t[k-1]
}

Usage:
# Assign the anonymous function to a variable
m = ->i{t,o,k=[],[],0;f=->n{t[n]||=n<3?1:f[n-2]+f[n-1]};(r=('%x'%f[k]).scan(/\d/).join.to_i;(r>1&&(r==2||(2...r).none?{|j|r%j==0}))&&o<<r;k+=1)while !o[i-1];t[k-1]}

m[2]
=> 3
m[19]
=> 7540113804746346429

R, 164 bytes
g=function(n){f=function(m)ifelse(m<3,1,f(m-1)+f(m-2));p=0;while(n){p=p+1;x=gsub("\\D","",sprintf("%x",f(p)));x[x==""]=1;y=1:x;if(sum(!tail(y,1)%%y)==2)n=n-1};f(p)}

Indented, with new lines:
g=function(n){
    f = function(m)ifelse(m<3,1,f(m-1)+f(m-2)) #Fibonacci function
    p = 0
    while(n){
        p = p+1
        x = gsub("\\D","",sprintf("%x",f(p))) #To Hex, and get rid of non-digits
        x[x==""] = 1 #If x is empty string
        y = 1:x #Converts to integer(!) and save the 1-to-x sequence to a variable
        if(sum(!tail(y,1)%%y)==2) n = n-1 #If prime, decrements counter
        }
    f(p)
    }

Examples:
> g(1)
[1] 2
> g(5)
[1] 89
> g(10)
[1] 121393
> g(12)
[1] 5702887

Husk, 13 bytes
!föṗdf≤9B16İf

Try it online!
Using Husk here is just about cheating cause it has an infinite fibonacci sequence builtin.
Explanation
!föṗdf≤9B16İf
           İf infinite list of fibonacci numbers
 fö           filtered on the following four functions:
        B16   base 16 digits of the number
     f≤9      filter out the digits > 9
    d         interpret in base 10
   ṗ          is that prime?
!             get element at input index

Jelly, 14 bytes
ÆḞb⁴<Ƈ⁵ḌẒµ#ṪÆḞ

Try it online!
Husk's infinite lists just beating me out.
How it works
ÆḞb⁴<Ƈ⁵ḌẒµ#ṪÆḞ - Main link. Takes no arguments
         µ#    - Read an integer n from STDIN and do the following for each integer, i = 0, 1, 2, ... until n return true and return the i's that return true:
ÆḞ             -   The ith Fibonacci number...
        Ẓ      -   ...is prime when...
  b⁴           -   ...converted to base-16,...
    < ⁵        -   ...values less than 10...
     Ƈ         -   ...are removed...
       Ḍ       -   ...then is converted back to base-10
           Ṫ   - Take the last i
            ÆḞ - Return the ith Fibonacci number

Vyxal, 11 bytes
ÞF'Hkd↔⌊æ;i

Try it Online!
Infinite Fibonacci and hexadecimal conversion builtins go brr
ÞF          # All fibonacci numbers
  '      ;i # Find the nth where...
   H        # In hexadecimal
    kd↔     # Keeping only digits
       ⌊æ   # Is it prime?

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Can the Array be Unshuffled?
Background
Very skilled card handlers are capable of a technique whereby they cut a deck perfectly in half, then perfectly interleave the cards. If they start with a sorted deck and perform this technique flawlessly 52 times in a row, the deck will be restored to sorted order. Your challenge is to take a deck of cards an integer array and determine whether it can be sorted using only Faro shuffles.
Definition
Mathematically, a Faro shuffle is a permutation on 2 n elements (for any positive integer n) which takes the element in position i (1-indexed) to position 2 i (mod 2 n+1). We would also like to be able to handle odd-length lists, so in that case, just add one element to the end of the list (a Joker, if you have one handy) and Faro shuffle the new list as above, but ignore the added dummy element when checking the list's order.
Goal
Write a program or function that takes a list of integers and returns or outputs  a truthy if some number of Faro shuffles would cause that list to be sorted in nondescending order (even if that number is zero--small lists should give a truthy). Otherwise,  return or output a falsy.
Examples
[1,1,2,3,5,8,13,21]  => True
[5,1,8,1,13,2,21,3] => True
[9,36,5,34,2,10,1] => True
[1,0] => True
[0] => True
[] => True
[3,2,1] => True
[3,1,2] => False
[9,8,7,6,5,4,3,2,1,0] => True
[9,8,7,6,5,4,3,2,0,1] => False
[3,1,4,1,5,9,2,6,9] => False
[-1,-1,-1,-2] => True

Scoring
This is code-golf so shortest source in bytes wins.

To avoid confusion with any fellow card handlers, it should be noted that there are two kinds of Faro shuffles. An in-shuffle and an out-shuffle. The method described here is an in-shuffle. Interestingly, it takes only 8 out-shuffles to return a deck to its original order. More Info

Isn't this just "in-shuffle N+1 times and see if any of the lists along the way are sorted"?

Actually n times is sufficient, because doing it 2n times is guaranteed to find all possible permutations, but you'll get at least one of either ascending or descending order in the first n.

Related. Related.

doesnt the first element always stay in the first position?

@Eumel no.  It always goes to the second position each shuffle.

To make sure I understood: a shuffle would transform 1 2 3 4 5 6 7 8 into 5 1 6 2 7 3 8 4, right?

MATL, 41 bytes
itn2\?YNh]tnt1+:"x[]2e!PY)ttZN~)tS=At.]wx

The output is 1 or 0.
Explanation
i              % get input array
tn2\           % is size odd?
?              % if that's the case
  YNh          % concat NaN at the end
]              % end if
tn             % get size of input array
t1+:           % vector 1:n+1, where n is input size, so loop will be entered even with []
"              % for loop
  x[]2e!PY)    % delete result from previous iteration and do the shuffling
  ttZN~)       % remove NaN, if there's any
  tS=A         % check if array is sorted
  t.           % copy the result. If true, break loop
]              % end for
wx             % remove unwanted intermediate result

Example
>> matl itn2\?YNh]tnt1+:"x[]2e!PY)ttZN~)tS=At.]wx
> [1,1,2,3,5,8,13,21]
1

Pyth - 26 25 24 bytes
Uses cumulative reduce to apply Faro shuffle multiple times and keep all the results. Then, it maps through it and checks if they are invariant under sorting, then uses sum to check is any are true. Returns a positive or zero.
smSI-db.usC_c2NQsC.tc2Qb

Test Suite.


text:
Rolling the Dice
Rolling the Dice
So, I was rolling dice a while ago and thought of a challenge.
Given the cube with a net taken from input and a list of moves, find the square on the bottom at the end.

I will use this image for the examples here.
Input
You take in a string with a list of moves.  The string contains only the capital ASCII letters N, S, W, and E.  These correspond to rolling the cube one step into that direction.
In the picture, one N would make the bottom face a 6.  In this image, North is away from the camera, South is towards, East is right, and West is left.
You also take in a string in the following format: 1P 2P 3P 4P 5P 6P, where each P is a position from N, S, W, E, T, and B.  T & B are bottom and top.
The numbers are the face with that number, and the letter represents the position the face is in.  In case it isn't clear, the net will always be ordered by the number, so 1P 2P 3P 4P 5P 6P, never 2B 1T 3N 4S 5W 6E.
The position in the image is 1S 2B 3E 4W 5T 6N.
Output
Your program should output a number representing the bottom side.
Test Cases
(nothing), 1S 2B 3E 4W 5T 6N -> 2
N, 1S 2B 3E 4W 5T 6N -> 6
NS, 1S 2B 3E 4W 5T 6N -> 2
NWS, 1S 2B 3E 4W 5T 6N -> 2
NWSNWS, 1S 2B 3E 4W 5T 6N -> 2
NWSS, 1S 2B 3E 4W 5T 6N -> 3
NNNNNN, 1S 2B 3E 4W 5T 6N -> 5
SNWEEWS, 1N 2T 3E 4W 5B 6S, 6
SNEEWS, 1N 2T 3W 4S 5B 6E, 4

Other Rules
You may also assume the cube is on a infinite flat plane, probably with some sort of friction.
Standard loopholes disallowed, even though I can't find any.
For invalid input, your code may do anything except start the apocalypse.
Because this program should fit on my dice, it should be as small as possible.  I count in bytes, with some exceptions for languages like Folders.

Does the first test case with (nothing) -> 2 mean that no net is provided, or should there be a net there somewhere?

"In the picture, one N would make the bottom face a 2" isn't the bottom face already a 2?

@Sp3000, edited, the net should be provided but your code should be able to handle no movement commands.

You measure the size of your dice in bytes?

@Cyoce No, just the text on each face.  So the face with  on it would be 4 bytes.  For this challenge, I want to be able to fit the code you write on my dice.  To do that, I need small code.

The last test case SNEEWS, 1N 2T 3W 4S 5B 6E isn't a valid die: opposite sides should sum to 7.

@Kenney I know, but it shouldn't make a difference for your program.  My dice are weird, as noted in the above comments.

CJam, 43 40 37 34 bytes
Thanks to Dennis for helping me save 6 bytes.
lW%3/$1f=q{i8%"ÉĔɠƂ!"=i\m!=}/c

Test it here.
Explanation
lW%    e# Read the first line and reverse it.
S/     e# Split it around spaces.
$      e# Sort it. This puts the faces in order [B E N S T W].
1f=    e# Select the second character from each face, which is the number.
q      e# Read the remainder of the input (the instructions).
{      e# For each instruction...
  i8%  e#   Convert the character (NWSE) to an integer and take modulo 8.
  "ÉĔɠƂ!"=i
       e#   Use that to (cyclically) index this string and convert *that* character
       e#   to an integer.
  \    e#   Swap with the list of faces.
  m!   e#   Generate all permutations of the faces.
  =    e#   Select the permutation corresponding to the above integer.
}/     e# At the end of the loop, the bottom face will be the first character.
c      e# Convert the string to a character, which discards everything but the bottom face.

As for how the mapping of instruction characters to permutations works, here is a handy table:
   i   8%  5%  ""=   i   [0 1 2 3 4 5]m!=

N  78   6   1   Ĕ   276  [2 1 4 0 3 5]
W  87   7   2   ɠ   608  [5 0 2 3 1 4]
S  83   3   3   Ƃ   386  [3 1 0 4 2 5]
E  69   5   0   É   201  [1 4 2 3 5 0]

I've included the 5% column because that is what the cyclic indexing into the string does implicitly. For the four permutations we can see that each of them leaves two (opposite) sides untouched and cyclically permutes the other four.

How do you represent the permutations as those Unicode characters? How does Ĕ represent the permutation of N [2 1 4 0 3 5]? I've been staring at it for hours.

@paulvs The character code of Ĕ is 276. 6e! gives you a list of all 720 permutations of [0 1 2 3 4 5]. And 276 happens to be the index of [2 1 4 0 3 5] in that list.

I wished more people would have answered, but you were the shortest.  Congrats.

Perl, 166 158 154 144 139 135 134 132 116 bytes
includes +1 for -p
s/(\d)(.)/$h{$2}=$1/eg;$N='NTSB',$S='STNB',$E='ETWB',$W='WTEB';map{@h{@l}=@h{(@l=$$_=~/./g)[1..3,0]}}/\w/g;$_=$h{B}

With comments:
                                    # example input: "NS, 1S 2B 3E 4W 5T 6N"
s/(\d)(.)/$h{$2}=$1/eg;             # construct %h ( S=>1, B=>2, E=>3, W=>4, B=>2, N=>6 )

                                    # = Transformations =
$N='NTSB',                          # N becomes T, T becomes S, S becomes B, B becomes N
$S='STNB',
$E='ETWB',
$W='WTEB';

map {                               # iterate the moves "NS"
    @h{ @l } =                      # LHS: bulk-assign new values; @l defined in RHS
      @h{                           # RHS: init @l, transform
          (@l=$$_=~/./g)            # get transform, put ('N','T','S','B') in @l for LHS
          [1..3,0]                  # construct a rotated slice for RHS
    }
} /\w/g;                            # match the movements in list context

$_=$h{B}                            # assign the bottom face to output.

Input file:
, 1S 2B 3E 4W 5T 6N
N, 1S 2B 3E 4W 5T 6N
NS, 1S 2B 3E 4W 5T 6N
NWS, 1S 2B 3E 4W 5T 6N
NWSNWS, 1S 2B 3E 4W 5T 6N
NWSS, 1S 2B 3E 4W 5T 6N
NNNNNN, 1S 2B 3E 4W 5T 6N
SNWEEWS, 1N 2T 3E 4W 5B 6S
SNEEWS, 1N 2T 3W 4S 5B 6E

Run with
perl -p dice.pl < input.txt

Output: 262223564

update 158 Using $N, $S, $E, $W global variables instead of %t = {N=>, S=>, E=>, $W=>} saves 8 bytes.
update 154 Since the requirement is that the program output a number, not printing the newline print "$h{B}\n" saves 4 bytes: print $h{B}.
update 144 Save 10 bytes by doing
($s)=/^(\w+),/;            s/(\d)(.)/$h{$2}=$1/eg;

instead of
($s,@i)=split /,? |\n/;    %h=reverse map{split//}@i;

update 139 Move the regex for the command to the end to eliminate a variable, saving 6 bytes.
update 135 Save 4 bytes on @l[0..3,0] instead of @l[1..3],$l[0].
update 134 Save 1 byte by using assignment @l=split//,$$_ as value.
update 132 Save 2 bytes by doing /^\w+/ && $& instead of /^(\w+)/ && $1.
update 129 Save 3 bytes by using -p instead of -n and assigning $_ for print.
update 116 Save 13 bytes by rewriting split//, /^\w+/ && $& into /^\w+/g.

Crossed out 44 is still regular 44.

Python 2, 204 bytes
Thought it was time to respond to my own question.
def x(p,m):
    d={p[3*i-2]:i for i in range(1,7)}
    for j in m:n=2if j in'NE'else-2;x='BSTN'if j in'NS'else'BETW';d[x[0]],d[x[1]],d[x[2]],d[x[3]]=d[x[1+n]],d[x[(2+n)%4]],d[x[(3+n)%4]],d[x[0+n]]
    print d['B']

Not very short, but works.
Run as:
x('1B 2T 3N 4S 5W 6E','SNEEWS')
#Output: 4

Edit: Counted bytes wrong.  Now longer. :(

BTW, thanks xnor for the python macro.


text:
Finding the smallest grid of squares
Inspiration from Puzzling.SE.
Suppose we have an m × n grid such that each element is a base 10 digit. We can read the numbers from such a grid so that we fix a starting element, go to one of the eight nearest coordinates and maintain that direction for zero to five steps. This allows you to read a one to five digit number from a grid if you concatenate the digits.
Your task is to write a program finding the smallest m × n grid from which the squares of the numbers 1 to 100 (inclusive) can be read.
For example, if the grid is:
00182
36495

then the squares of 1-10 can be read from it, but, for example, 121 is missing. In this rectangle m × n = 2 × 5 = 10.
The winner is the code which generates the smallest grid.

Please write it up as a separate problem here, instead of just posting a link.

Welcome to Programming Puzzles and Code Golf! As it currently stands, this question is not a valid challenge as outlined in the help center. Please edit your question to those specifications and next time, please Use The Sandbox before posting.

The criterion for the grid is still very unclear. please add more examples and test cases.

I can try to clarify. What part of the puzzle is unclear?

in the end of the first paragraph, it says " you don't have to go to that direction any number of steps so you can also read the numbers 1, 4, and 9." Can you edit the post to explain in a more understandable way what you mean?

It means that you can read one to five digit numbers and you can't read for example 121 in the 2x1 grid 1 2.

There are at least two things which are unclear: 1. The definition of which numbers are contained in the grid; 2. The tie-breaker to distinguish between brute-force programs which are guaranteed to generate the smallest grid (although they might not actually do so in any reasonable time).

I meant that you read digits and then catenate it to form 1 to 5 digit numbers. Brute force programs are okay but you just have to output the grid.

How can you read the digits? In a straight line? Orthogonally? Diagonally? Forwards? Backwards? Snaking?

By straight line. What else could the "maintain that direction mean"?

Why this it unclear what I'm asking. I think "The winner is the code which generates the smallest grid." is very clear criterion.

I think I could probably rewrite the question to clarify the definition of the numbers in the grid, but that wouldn't fix the problem of the winning condition. "The one which generates the smallest grid" is perfectly clear, but also almost entirely useless, because the most likely case is that every single answer submitted would be optimal, so they would all be "winners".