# Billy Lost his Pen

tl;dr [True] Billy got a Stack Overflow pen from Tim Post. Billy was stupid enough to use the pen, knowing that he was not worthy. Billy's friend took the pen apart, so Billy put the pen in a drawer at his house, hoping he would eventually fix it. A year later, Billy can only find half of the pen's pieces, and not the main part that has the words "Stack Overflow" on it. [EndTrue] [Fake] Billy looked at his home security camera and saw that a burglar had come in his house while he was sleeping and taken his pen. Billy vows revenge! Why can't he just ask for another Stack Overflow pen? Because this is the last one in existence. [EndFake] Err, technically this whole thing is fake because my name isn't Billy.

Help Billy find the scumbag that stole his pen so he can ultimately deal mortal damage to him and get the other half of his pen back! You will use a World object that has the following methods:

objectsAtPosition(lon: Number, lat: Number)


This returns an array of strings. One string for every object at the specified longitude (lon) and latitude (lat). The possible strings are:

SUP - Super User Pen

SFP - Server Fault Pen

SOP - Stack Overflow Pen

BD - Bad Dog

GD - Good Dog

G - Giygas

destroyObjectAt(lon: Number, lat: Number, i)


This destroys the object at the specified longitude, latitude, and index. For example, if at a specified longitude (lon) and latitude (lat) there are two or more objects, destroy the nth object in the array depending on what the index (i) is. You will destroy every Giygas and every Bad Dog.

giveTreatToObjectAt(lon: Number, lat: Number, i)


This gives a treat to the object at the specified longitude (lon), latitude (lat), and index. For example, if at a specified longitude (lon) and latitude (lat) there are two or more objects, give a treat to the nth object in the array depending on what the index (i) is. You will give all good dogs a treat.

collectObjectAt(lon: Number, lat: Number, i)


This collects the object at the specified longitude (lon) and latitude (lat), and index. For example, if at a specified longitude (lon) and latitude (lat) there are two or more objects, collect the nth object in the array depending on what the index (i) is. You will collect Billy's Stack Overflow pen and nothing else or else you die. Keep in mind that there is only Billy's Stack Overflow pen left in existence.

You will index through every longitude and latitude value (look below) and treat every object found as they should be treated.

Longitude and latitude rage from 0-10. Iterate incrementing by 1. Treat lon and lat as integers if you'd like. Use whatever-based indexing the language you're coding this in uses. This is , so shortest bytes in code wins.

Every item is an array. Here's an example of what the Array would be like. It's a 2D Array, 10x10. Longitude brings you right and latitude brings you down. So longitude with 5 and latitude with 4 would select this:

['SO','SU'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example']
['SO','SU'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example']
['SO','SU'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example']
['SO','SU'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example']
['SO','SU'],['Example'],['Example'],['Example'],['Example'],['*Example*'],['Example'],['Example'],['Example'],['Example']
['SO','SU'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example']
['SO','SU'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example']
['SO','SU'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example']
['SO','SU'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example']
['SO','SU'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example'],['Example']


or

0→[item]1→[item]2→[item]3→[item]4→[item]5→[item]0↓[item][item][item][item]
[item]  [item]  [item]  [item]  [item]  [item]1↓[item][item][item][item]
[item]  [item]  [item]  [item]  [item]  [item]2↓[item][item][item][item]
[item]  [item]  [item]  [item]  [item]  [item]3↓[item][item][item][item]
[item]  [item]  [item]  [item]  [item][*item*]←4[item][item][item][item]
[item]  [item]  [item]  [item]  [item]  [item]  [item][item][item][item]
[item]  [item]  [item]  [item]  [item]  [item]  [item][item][item][item]
[item]  [item]  [item]  [item]  [item]  [item]  [item][item][item][item]
[item]  [item]  [item]  [item]  [item]  [item]  [item][item][item][item]
[item]  [item]  [item]  [item]  [item]  [item]  [item][item][item][item]


In case you don't see it, it will select the item "Example" in the first one and the item "item" in the second one. I'm not sure how the human brain works, use your browser's search on page feature if you still don't see it.

PS:

If you don't know what a Giygas is, just know that you have to destroy it... or pray for your life by it (which ultimately destroys it anyway).

• Geobits' SO mug gets used by family members all the time, but at least it isn't lost (yet). – Geobits Jan 20 '15 at 2:33
• @Geobits My SO mug was used by my 7-year-old cousin once who got it all dry in hot chocolate :/ – Cilan Jan 20 '15 at 2:44
• Can we rename the "World" object or the methods that are provided by it, or do we use them named as stated? – BMac Jan 20 '15 at 4:51
• After doing the problem, I think it could be more interesting if the API provided the world contents in a jagged 3d array or something like that. The fact that a method has to be called for each cell really forces you into some kind of iteration - in-memory data might allow for some Linq tricks or crazy pointer arithmetic. – BMac Jan 20 '15 at 6:11
• @BMac So it's fair for everyone and easy to read (because we can't really run these) use the names provided. If the names are conflicting in any way, please tell me. – Cilan Jan 20 '15 at 13:15

# C# - 272 bytes

I couldn't find too many tricks to do here outside of some for-loop shenanigans. I was hoping to use some Linq, but the index parts of the API made it difficult to make that work concisely.

class A{static void Main(string[] a){
for(int x=101,y,c;x-->0;)
for(y=101;y-->(c=0);)
foreach(string s in World.objectAtPosition(x,y)){
if(s=="SOP")World.collectObjectAt(x,y,c);
if(s=="BD"||s=="G")World.destroyObjectAt(x,y,c);
if(s=="GD")World.giveTreatToObjectAt(x,y,c);
c++;}}}


Here's my test code:

using System.Linq;
class A
{
static void Main(string[] a)
{
for (int d = 0; d < 100; d++)
{
World.populate();

for(int x=101,y,c;x-->0;)
for(y=101;y-->(c=0);)
foreach(string s in World.objectAtPosition(x,y))
{
if(s=="SOP")World.collectObjectAt(x,y,c);
if(s=="BD"||s=="G")World.destroyObjectAt(x,y,c);
if(s=="GD")World.giveTreatToObjectAt(x,y,c);
c++;
}

World.verify();
}
}

static class World
{
private static System.Collections.Generic.List<Item>[,] m_Map =
new System.Collections.Generic.List<Item>[maxRange+1, maxRange+1];

private static System.Random random = new System.Random();

private const int maxRange = 100;
private const int dogCount = 20;

private class Item
{
public string id;
public bool handled;

public Item(string id)
{
this.id = id;
this.handled = false;
}
}

public static void populate()
{
for (int lat = 0; lat <= maxRange; lat++)
for (int lon = 0; lon <= maxRange; lon++)
m_Map[lat, lon] = new System.Collections.Generic.List<Item>();
for (int c = 0; c < dogCount; c++)
{
}
}

public static void verify()
{
for (int lat = 0; lat <= maxRange; lat++)
{
for (int lon = 0; lon <= maxRange; lon++)
{
for (int index = 0; index < m_Map[lat, lon].Count; index++)
{
Item item = m_Map[lat, lon][index];
if (!item.handled && item.id != "SUP" && item.id != "SFP")
{
throw new System.Exception(string.Format("Didn't handle '{0}' at '{1},{2}:{3}'.",
item.id, lat, lon, index));
}
}
}
}
}

private static int randomCoord()
{
return random.Next(maxRange + 1);
}

{
int lat = randomCoord();
int lon = randomCoord();
}

public static string[] objectAtPosition(int lat, int lon)
{
return m_Map[lat, lon].Select(item => item.id).ToArray();
}

public static void destroyObjectAt(int lat, int lon, int index)
{
Item item = m_Map[lat, lon][index];
if (item.id == "G" || item.id == "BD")
item.handled = true;
else
throw new System.InvalidOperationException(string.Format("Tried to destroy '{0}' at '{1},{2}-{3}'",
item.id, lat, lon, index));
}

public static void giveTreatToObjectAt(int lat, int lon, int index)
{
Item item = m_Map[lat, lon][index];
if (item.id == "GD")
item.handled = true;
else
throw new System.InvalidOperationException(string.Format("Tried to giveTreatTo '{0}' at '{1},{2}-{3}'",
item.id, lat, lon, index));
}

public static void collectObjectAt(int lat, int lon, int index)
{
Item item = m_Map[lat, lon][index];
if (item.id == "SOP")
item.handled = true;
else
throw new System.InvalidOperationException(string.Format("Tried to collect '{0}' at '{1},{2}-{3}'. You die.",
item.id, lat, lon, index));
}
}
}