Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# 1st Solidity Gas Golfing Contest

The Solidity Gas Golfing Contest is a competition for Solidity coders to produce the most gas-efficient code they can for a series of straightforward challenges. The 1st SGGC will run from 25 May to 25 June 2018.
The Solidity Gas Golfing Contest is a competition for Solidity coders to produce the most gas-efficient code they can for a series of straightforward challenges. The 1st SGGC will run from 23 May to 30 June 2018.

For more details, and entry instructions, see the competition site at [g.solidity.cc](http://g.solidity.cc/).

This repository contains boilerplate for the contracts for each of the five challenges, along with test vectors and runners to test your implementation against before submitting it.

Note that constructor code will not be run, and state will not persist between tests.

## Installation

Clone this repository and install its dependencies:
Expand Down
58 changes: 58 additions & 0 deletions contracts/BrainFuck.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,63 @@ contract BrainFuck {
* number of outputs produced by the program.
*/
function execute(bytes program, bytes input) public pure returns(bytes) {
uint ipp = 0;
uint opp = 0;
uint dp = 0;
bytes memory mem = new bytes(1024);
bytes memory output = new bytes(1024);

for(uint ip = 0; ip < program.length; ip++) {
byte instruction = program[ip];
if(instruction == '+') {
mem[dp] = byte(uint(mem[dp]) + 1);
} else if(instruction == '-') {
mem[dp] = byte(uint(mem[dp]) - 1);
} else if(instruction == '>') {
dp++;
} else if(instruction == '<') {
dp--;
} else if(instruction == '.') {
output[opp++] = mem[dp];
} else if(instruction == ',') {
mem[dp] = input[ipp++];
} else if(instruction == '[') {
if(mem[dp] == 0) {
uint depth = 1;
for(uint i = ip + 1; i < program.length; i++) {
if(program[i] == ']') {
depth--;
if(depth == 0) {
ip = i;
break;
}
} else if(program[i] == '[') {
depth++;
}
}
}
} else if(instruction == ']') {
if(mem[dp] != 0) {
depth = 1;
for(i = ip - 1; i > 0; i--) {
if(program[i] == '[') {
depth--;
if(depth == 0) {
ip = i;
break;
}
} else if(program[i] == ']') {
depth++;
}
}
}
}
}

bytes memory ret = new bytes(opp);
for(i = 0; i < opp; i++) {
ret[i] = output[i];
}
return ret;
}
}
15 changes: 15 additions & 0 deletions contracts/HexDecoder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@
pragma solidity 0.4.24;

contract HexDecoder {
function hexchr(byte input) private pure returns(uint8) {
if(input >= 0x30 && input <= 0x39) {
return uint8(input) - 0x30;
} else if(input >= 0x41 && input <= 0x46) {
return uint8(input) - 0x37;
} else if(input >= 0x61 && input <= 0x67) {
return uint8(input) - 0x57;
}
}

/**
* @dev Decodes a hex-encoded input string, returning it in binary.
*
Expand All @@ -18,5 +28,10 @@ contract HexDecoder {
* @return The decoded output.
*/
function decode(string input) public pure returns(bytes output) {
require(bytes(input).length % 2 == 0);
output = new bytes(bytes(input).length / 2);
for(uint i = 0; i < output.length; i++) {
output[i] = byte((hexchr(bytes(input)[i * 2]) << 4) | hexchr(bytes(input)[i * 2 + 1]));
}
}
}
18 changes: 18 additions & 0 deletions contracts/IndexOf.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@
pragma solidity 0.4.24;

contract IndexOf {
function equals(string haystack, uint i, string needle) private pure returns(bool) {
for(uint j = 0; j < bytes(needle).length; j++) {
if(bytes(haystack)[i + j] != bytes(needle)[j]) {
return false;
}
}
return true;
}

/**
* @dev Returns the index of the first occurrence of `needle` in `haystack`,
* or -1 if `needle` is not found in `haystack`.
Expand All @@ -19,5 +28,14 @@ contract IndexOf {
* @return The index of `needle` in `haystack`, or -1 if not found.
*/
function indexOf(string haystack, string needle) public pure returns(int) {
if(bytes(needle).length > bytes(haystack).length) {
return -1;
}
for(uint i = 0; i <= bytes(haystack).length - bytes(needle).length; i++) {
if(equals(haystack, i, needle)) {
return int(i);
}
}
return -1;
}
}
23 changes: 23 additions & 0 deletions contracts/Sort.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,28 @@ contract Sort {
* @return The sorted list.
*/
function sort(uint[] input) public pure returns(uint[]) {
sort(input, 0, int(input.length - 1));
return input;
}

function sort(uint[] input, int lo, int hi) internal pure {
if(lo < hi) {
int p = partition(input, lo, hi);
sort(input, lo, p - 1);
sort(input, p + 1, hi);
}
}

function partition(uint[] input, int lo, int hi) internal pure returns(int) {
uint pivot = input[uint(hi)];
int i = lo - 1;
for(int j = lo; j < hi; j++) {
if(input[uint(j)] < pivot) {
i += 1;
(input[uint(i)], input[uint(j)]) = (input[uint(j)], input[uint(i)]);
}
}
(input[uint(i + 1)], input[uint(hi)]) = (input[uint(hi)], input[uint(i + 1)]);
return i + 1;
}
}
20 changes: 20 additions & 0 deletions contracts/Unique.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
pragma solidity 0.4.24;

contract Unique {
function isUnique(uint[] input, uint len, uint value) private pure returns(bool) {
for(uint i = 0; i < len; i++) {
if(input[i] == value) return false;
}
return true;
}

/**
* @dev Removes all but the first occurrence of each element from a list of
* integers, preserving the order of original elements, and returns the list.
Expand All @@ -18,5 +25,18 @@ contract Unique {
* @return The input list, with any duplicate elements removed.
*/
function uniquify(uint[] input) public pure returns(uint[] ret) {
uint ptr = 0;
for(uint i = 0; i < input.length; i++) {
if(isUnique(input, i, input[i])) {
input[ptr++] = input[i];
}
}

ret = new uint[](ptr);
for(i = 0; i < ret.length; i++) {
ret[i] = input[i];
}

return ret;
}
}
43 changes: 36 additions & 7 deletions data/BrainFuck.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,50 @@
"vectors": [
{
"gas": 100000,
"input": [",>,<[->+<]>.", "0x0101"],
"output": ["0x02"],
"comment": "Adds 1 and 1"
"input": [",>,<[->+<]>.", "0x0305"],
"output": ["0x08"],
"comment": "Adds 3 and 5"
},
{
"gas": 500000,
"input": [",>,<[->+<]>.", "0x1010"],
"output": ["0x20"],
"comment": "Adds 16 and 16"
"input": [",>,<[->+<]>.", "0x0910"],
"output": ["0x19"],
"comment": "Adds 9 and 17"
},
{
"gas": 2000000,
"input": ["++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.", "0x"],
"input": ["++++++++[!!>++++[??>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]Boo>>.>---.+++++++..+++.>>.<-.<.+++.Fnord------.--------.>>+.>++.", "0x"],
"output": ["0x48656c6c6f20576f726c64210a"],
"comment": "Prints Hello World!"
},
{
"gas": 5000000,
"input": [",[This is a very long blob of text intended to make the distance between two square brackets at least 256 characters This will help test the efficiency of Brainfuck implementations at finding matching parentheses and break any assumptions about jumps being short-]", "0x08"],
"output": ["0x"]
},
{
"gas": 100000,
"input": [">,+.<.", "0xff"],
"output": ["0x0000"],
"comment": "Test integer overflow"
},
{
"gas": 100000,
"input": [">-.<.", "0x"],
"output": ["0xff00"],
"comment": "Test integer underflow"
},
{
"gas": 3000000,
"input": [",[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>,],.", "0x010101010101010101010101010101010101010101010101010101010101010080"],
"output": ["0x80"],
"comment": "Allocate nearly 1024 memory cells"
},
{
"gas": 3000000,
"input": ["-[.-]..", "0x"],
"output": ["0xfffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a09f9e9d9c9b9a999897969594939291908f8e8d8c8b8a898887868584838281807f7e7d7c7b7a797877767574737271706f6e6d6c6b6a696867666564636261605f5e5d5c5b5a595857565554535251504f4e4d4c4b4a494847464544434241403f3e3d3c3b3a393837363534333231302f2e2d2c2b2a292827262524232221201f1e1d1c1b1a191817161514131211100f0e0d0c0b0a0908070605040302010000"],
"comment": "Output lots of values"
}
]
}
31 changes: 23 additions & 8 deletions data/HexDecoder.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,33 @@
},
{
"gas": 100000,
"input": ["666f6f"],
"output": ["0x666f6f"]
"input": ["aaBBcCDd"],
"output": ["0xaabbccdd"]
},
{
"gas": 100000,
"input": ["666F6F"],
"output": ["0x666f6f"]
"gas": 1000000,
"input": ["4ba90007bb11e118b90185586876687b0487c391d721948b846bd4633deba10662125e4acf7a275834d37850dc270cf6d9413d23d7b85f1f2863b8d2ef16d83f"],
"output": ["0x4ba90007bb11e118b90185586876687b0487c391d721948b846bd4633deba10662125e4acf7a275834d37850dc270cf6d9413d23d7b85f1f2863b8d2ef16d83f"]
},
{
"gas": 100000,
"input": ["0102030405"],
"output": ["0x0102030405"]
"gas": 1000000,
"input": ["b0f4a8174d10e52454adbcb4d70fc7e05c047f4dddacc71594491fb5ba8a522be05dc726e3baeeff888c3c50998e9b8779e3e712d2c930686429d0965dd8dad83a3d2d19bd22c735f8457da8d204801b377ae36287c160d8d9e2ca49da96c409af93d531f63b15f98523cbc2147394bbedd77b9004bee4e7b50125129225324e"],
"output": ["0xb0f4a8174d10e52454adbcb4d70fc7e05c047f4dddacc71594491fb5ba8a522be05dc726e3baeeff888c3c50998e9b8779e3e712d2c930686429d0965dd8dad83a3d2d19bd22c735f8457da8d204801b377ae36287c160d8d9e2ca49da96c409af93d531f63b15f98523cbc2147394bbedd77b9004bee4e7b50125129225324e"]
},
{
"gas": 1000000,
"input": ["144eb41ca56f4d54794b895ff9bfbac46393efe8b1a40dbd9fa587d8e41b952427dd9757ad840df1acc606024968dd8125208cbd4db785750c12e655d5074b845e58741c1c188ea8ee1c6b162a00cb68acd9fca24681bcc65defc88f8dc4ed7fc2557f191c8e80b7ce9fe6922f70a1631f98b9c474e2b0a824e9093900eed690b01e121a87a648c6a3d3cd32bc70f647be2fafe0f51bd64a4e948a850ec4fa69fb28899d452d8ebc506653d3472af9573d994978257bac39369a829d1e6b3f339cba5bf1c56a8df770f259a51117721fb79faf2dcdd9a04ce36d5632d0fa20d73edf95f9c0746ce03b84569f4fb823b00d132e7f6d11221c84425165755917be"],
"output": ["0x144eb41ca56f4d54794b895ff9bfbac46393efe8b1a40dbd9fa587d8e41b952427dd9757ad840df1acc606024968dd8125208cbd4db785750c12e655d5074b845e58741c1c188ea8ee1c6b162a00cb68acd9fca24681bcc65defc88f8dc4ed7fc2557f191c8e80b7ce9fe6922f70a1631f98b9c474e2b0a824e9093900eed690b01e121a87a648c6a3d3cd32bc70f647be2fafe0f51bd64a4e948a850ec4fa69fb28899d452d8ebc506653d3472af9573d994978257bac39369a829d1e6b3f339cba5bf1c56a8df770f259a51117721fb79faf2dcdd9a04ce36d5632d0fa20d73edf95f9c0746ce03b84569f4fb823b00d132e7f6d11221c84425165755917be"]
},
{
"gas": 1000000,
"input": ["81b044e53a17905956027d2d0b7cf2d65faaa876722830e1aff90758b2ae60fcf239f558d2e569e057dde0a991f7fdf484c660a59c185cc4d529491219cf3eb26312e72736c9a6b795869b4aec675411c83b348a9eb2075f2b5dee5be01ba38d2d543934f5d1c473aecb67d3cb8649d7db58e49d1c3ac23a854a1b70e0d0940b5bcc8fae352f615b4268b49d2f2676ee352ad175c19c3b382b13cc8c957e67e10c5da203f026a60327d385b3df4825b4ff7708f8f6647251ee8936a1715f02ccc0e4339aa3c38d2f4cdc8c315c15b63c1bc8cb9d1faa167b393de15a0cf7bc363252954542ad0651b72980e431648bca3e592ce7537a79a961d1320314e48c5caad8c0789401c5e9ddc6b0cd79a05f48948e9a152dd0e483ae062cb91f57ccb3fc01f3298fa68146f6d7cf2384a5d506c1a42627b943cb95848e1d23dabfe4d6b3b895dd3f0195883eeb53c96a046e054f8b8cc939bd65c5a8465c417b85ef501a13559fba3bd0fe362e14acceece550ae9b46d9517e5ebd94abc308161c98459ebc251218c94c549b90f9a93d9f48e29d5d1f68a41532544750ab0009830432520c5511b169adb823c1eaa29c39336a1087d1230cc77bdf3e71683057ebc52bca6b6490717366c36f0d53f031486d59be8b599b3e8f858e5c05d763d9c10716ed227e40f6e625e3401ca358a8d6e8a75c7dec2c8203191eeb9d61353fc53f83"],
"output": ["0x81b044e53a17905956027d2d0b7cf2d65faaa876722830e1aff90758b2ae60fcf239f558d2e569e057dde0a991f7fdf484c660a59c185cc4d529491219cf3eb26312e72736c9a6b795869b4aec675411c83b348a9eb2075f2b5dee5be01ba38d2d543934f5d1c473aecb67d3cb8649d7db58e49d1c3ac23a854a1b70e0d0940b5bcc8fae352f615b4268b49d2f2676ee352ad175c19c3b382b13cc8c957e67e10c5da203f026a60327d385b3df4825b4ff7708f8f6647251ee8936a1715f02ccc0e4339aa3c38d2f4cdc8c315c15b63c1bc8cb9d1faa167b393de15a0cf7bc363252954542ad0651b72980e431648bca3e592ce7537a79a961d1320314e48c5caad8c0789401c5e9ddc6b0cd79a05f48948e9a152dd0e483ae062cb91f57ccb3fc01f3298fa68146f6d7cf2384a5d506c1a42627b943cb95848e1d23dabfe4d6b3b895dd3f0195883eeb53c96a046e054f8b8cc939bd65c5a8465c417b85ef501a13559fba3bd0fe362e14acceece550ae9b46d9517e5ebd94abc308161c98459ebc251218c94c549b90f9a93d9f48e29d5d1f68a41532544750ab0009830432520c5511b169adb823c1eaa29c39336a1087d1230cc77bdf3e71683057ebc52bca6b6490717366c36f0d53f031486d59be8b599b3e8f858e5c05d763d9c10716ed227e40f6e625e3401ca358a8d6e8a75c7dec2c8203191eeb9d61353fc53f83"]
},
{
"gas": 2000000,
"input": ["3a6ce44d45b3cfcb5f457785f945015600656e80a28d79e97574971c7b8019b1bf96aa6ef1d1c3fa514fac5ec567fe07cc1685bda5a05b3ea9a1bbd677b924ad7d3560e11a784c16acb91a4afcbcec832d2e888053b0b261226a482bdae50a6ee287fd0e84056cc67e987c9438a24aae0085f84a7613761d86a4de4207d106f510f4b9ea05b4c2bd7230d106e140dc4b406efa3f1839a2e5b6d09ef7fc2dc756788b149c7a566556cef7084db77b80fae136a1d414d169f88db9ff0ae2321d242d4d145e259a77c1aba23a1ed8c39095673fc2766cab3727b788780c14c363129b9df9da501eced3598747f549781904f399eaf6e237e84dcd4e95accfe4817ccda868a024deb0de68e8a2b11d8c98b0229118b524c7831c09976df6c6435d7f3c2aa574884970d7c3fafabc2382f634718ac4c7cf4218b4c96ea254996e8fe9acfac3b7933223a0310a71c78a69ae445a18dd08bc8a864d15e2cfe50071c63e2fdac9ae0588f386b689af369f471b44cebe4d752cd4e468a59284f666c7d1276ca3c36bcc315f10c84d571ac502e710e3551ebfdb42e0bf031eee3f944ea369703d370c22ab91f3a483f12e0a247d1e75e2dc2e3ca5a5f495d23dbacd8f86133edd80ee6a6f92dbf05b09bfc369a08efa6c3b97dc6854f26a69c6d03c55d0fc182b1c723244295068dfa17e3f92ba7b944d85d169aed440bd0069df74e61b2823c06f8c6c1d7737ed8ec764fc6115b47dfd12dc363bd0afe20026370d70399e07c1c757102e59675561bdfac0a252cb144d87fd8ea0a0a82e69107b8134a14f8ef17274a763ee3a6d7a97520d3ad3fa1c6fbc34bd70585f0bf16e5b9a6a7091f878c12f5546cd3fd17d9140b50c1096646e39cc618c1a66f816447fdd3d0e3b1e2514b57449cc9ee38dfb162b0ed4898cd2fd9b28105141160c96a1537ffe0ce5aadc77996fc8730d6f43e51a69ca51bb9a968390689d75afc7c509e442dfa73c6d63addf9415d56509a9ef972f3438d6795ccfdfed148f837b163c1716c84e97c1ee8ac1877189646e5f9d263bb46bb529b06a20e423fcf4cd556fe34f2b19b79b842a9789c343d298c31514e747dc2041b94fcd26962bfe90fb623882563cb5e450c562cab8447d2284cb63432167ee4597e8fbcfbf1ce4ada647aafe168ed55acc5fb80e565c44706bac10d4903d63450e8bba4b8221153480176acb8191840d423df10cc5b314d77d27c66802a82ac3a31d3678f17be1110d760a0d8eedf106c73441445bf2403caf0fa15db1313208b09359d556e96f5e2e70de8988006c0b2bf13ef5c12e3f1f11ad76457ca1ede2ad4c6a45b6c239a4f79f916b9c8216074f7ce9e8d0b56f90bbfbb106a8f72811693644eff8d06f12ebfff32969679b7a2a79b5039d558c70e0d0255d27f448af8f2c9e4da190c02428f063243cce"],
"output": ["0x3a6ce44d45b3cfcb5f457785f945015600656e80a28d79e97574971c7b8019b1bf96aa6ef1d1c3fa514fac5ec567fe07cc1685bda5a05b3ea9a1bbd677b924ad7d3560e11a784c16acb91a4afcbcec832d2e888053b0b261226a482bdae50a6ee287fd0e84056cc67e987c9438a24aae0085f84a7613761d86a4de4207d106f510f4b9ea05b4c2bd7230d106e140dc4b406efa3f1839a2e5b6d09ef7fc2dc756788b149c7a566556cef7084db77b80fae136a1d414d169f88db9ff0ae2321d242d4d145e259a77c1aba23a1ed8c39095673fc2766cab3727b788780c14c363129b9df9da501eced3598747f549781904f399eaf6e237e84dcd4e95accfe4817ccda868a024deb0de68e8a2b11d8c98b0229118b524c7831c09976df6c6435d7f3c2aa574884970d7c3fafabc2382f634718ac4c7cf4218b4c96ea254996e8fe9acfac3b7933223a0310a71c78a69ae445a18dd08bc8a864d15e2cfe50071c63e2fdac9ae0588f386b689af369f471b44cebe4d752cd4e468a59284f666c7d1276ca3c36bcc315f10c84d571ac502e710e3551ebfdb42e0bf031eee3f944ea369703d370c22ab91f3a483f12e0a247d1e75e2dc2e3ca5a5f495d23dbacd8f86133edd80ee6a6f92dbf05b09bfc369a08efa6c3b97dc6854f26a69c6d03c55d0fc182b1c723244295068dfa17e3f92ba7b944d85d169aed440bd0069df74e61b2823c06f8c6c1d7737ed8ec764fc6115b47dfd12dc363bd0afe20026370d70399e07c1c757102e59675561bdfac0a252cb144d87fd8ea0a0a82e69107b8134a14f8ef17274a763ee3a6d7a97520d3ad3fa1c6fbc34bd70585f0bf16e5b9a6a7091f878c12f5546cd3fd17d9140b50c1096646e39cc618c1a66f816447fdd3d0e3b1e2514b57449cc9ee38dfb162b0ed4898cd2fd9b28105141160c96a1537ffe0ce5aadc77996fc8730d6f43e51a69ca51bb9a968390689d75afc7c509e442dfa73c6d63addf9415d56509a9ef972f3438d6795ccfdfed148f837b163c1716c84e97c1ee8ac1877189646e5f9d263bb46bb529b06a20e423fcf4cd556fe34f2b19b79b842a9789c343d298c31514e747dc2041b94fcd26962bfe90fb623882563cb5e450c562cab8447d2284cb63432167ee4597e8fbcfbf1ce4ada647aafe168ed55acc5fb80e565c44706bac10d4903d63450e8bba4b8221153480176acb8191840d423df10cc5b314d77d27c66802a82ac3a31d3678f17be1110d760a0d8eedf106c73441445bf2403caf0fa15db1313208b09359d556e96f5e2e70de8988006c0b2bf13ef5c12e3f1f11ad76457ca1ede2ad4c6a45b6c239a4f79f916b9c8216074f7ce9e8d0b56f90bbfbb106a8f72811693644eff8d06f12ebfff32969679b7a2a79b5039d558c70e0d0255d27f448af8f2c9e4da190c02428f063243cce"]
}
]
}
Loading