A couple of years ago, my friend wanted to learn programming, so I was giving her a hand with resources and reviewing her code. She got to the part on adding code comments, and wrote the now-infamous line,
i = i + 1 #this increments i
We’ve all written superflouous comments, especially as beginners. And it’s not even really funny, but for whatever reason, somehow we both remember this specific line years later and laugh at it together.
Years later (this week), to poke fun, I started writing sillier and sillier ways to increment i
:
Beginner level:
# this increments i:
x = i
x = x + int(True)
i = x
Beginner++ level:
# this increments i:
def increment(val):
for i in range(val+1):
output = i + 1
return output
Intermediate level:
# this increments i:
class NumIncrementor:
def __init__(self, initial_num):
self.internal_num = initial_num
def increment_number(self):
incremented_number = 0
# we add 1 each iteration for indexing reasons
for i in list(range(self.internal_num)) + [len(range(self.internal_num))]:
incremented_number = i + 1 # fix obo error by incrementing i. I won't use recursion, I won't use recursion, I won't use recursion
self.internal_num = incremented_number
def get_incremented_number(self):
return self.internal_num
i = input("Enter a number:")
incrementor = NumIncrementor(i)
incrementor.increment_number()
i = incrementor.get_incremented_number()
print(i)
Since I’m obviously very bored, I thought I’d hear your take on the “best” way to increment an int in your language of choice - I don’t think my code is quite expert-level enough. Consider it a sort of advent of code challenge? Any code which does not contain the comment “this increments i:” will produce a compile error and fail to run.
No AI code pls. That’s no fun.
First, imagine a number in JavaScript. (Bit of a nail biter here, huh?)
let i = 5
Then, we will construct an incrementor. This is really simple: here is the method.
- Make a bracket-string-centric version of
eval()
.
[]["filter"]["constructor"]("return i+1")()
- Reconstruct stringy
eval()
by using+[]
as 0,+!+[]
as 1, and implicit conversions as ways to create strings. For example, ‘false’ is(![]+[])
, so ‘f’ is(![]+[])[+[]]
.
[][ (![] + [])[+[]] + // f ([![]] + [][[]])[+!+[] + [+[]]] + // i (![] + [])[!+[] + !+[]] + // l (!![] + [])[+[]] + // t (!![] + [])[!+[] + !+[] + !+[]] + // e (!![] + [])[+!+[]] // r ][ ([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+ // c (!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+ // o ([][[]]+[])[+!+[]]+ // n (![]+[])[!+[]+!+[]+!+[]]+ // s (!![]+[])[+[]]+ // t (!![]+[])[+!+[]]+ // r ([][[]]+[])[+[]]+ // u ([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+ // c (!![]+[])[+[]]+ // t (!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+ // o (!![]+[])[+!+[]] // r ]("return i+1")()
- Draw the rest of the fucking owl. Final code:
let i = 5; // haha yay [][ (![] + [])[+[]] + // f ([![]] + [][[]])[+!+[] + [+[]]] + // i (![] + [])[!+[] + !+[]] + // l (!![] + [])[+[]] + // t (!![] + [])[!+[] + !+[] + !+[]] + // e (!![] + [])[+!+[]] // r ][ ([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+ // c (!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+ // o ([][[]]+[])[+!+[]]+ // n (![]+[])[!+[]+!+[]+!+[]]+ // s (!![]+[])[+[]]+ // t (!![]+[])[+!+[]]+ // r ([][[]]+[])[+[]]+ // u ([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+ // c (!![]+[])[+[]]+ // t (!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+ // o (!![]+[])[+!+[]] // r ]( (!![]+[])[+!+[]]+ // r (!![]+[])[!+[]+!+[]+!+[]]+ // e (!![]+[])[+[]]+ // t ([][[]]+[])[+[]]+ // u (!![]+[])[+!+[]]+ // r ([][[]]+[])[+!+[]]+ // n (+[![]]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+!+[]]]+ // ' ' ([![]]+[][[]])[+!+[]+[+[]]]+ // i (+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]])+[])[!+[]+!+[]]+ // + +!+[] // 1 )() // no virus i swear. execute arbitrary code in your browser console.
Anyway, that’s just everyday JS work. It’s like step 5 after resizing the button, but a bit before centering the div.
based on this. some translation methods done differently.
- Make a bracket-string-centric version of
Conditional adder:
if x==1: return 2 else if x==2: return 3 ...
Can’t increment negative numbers or zero smh.
Fix:
if x==0: return 1 else x==1: return 2 else if x==-1: return 0 else if x==2 return 3 else if x==-2 return -1 ...
Hard to beat this. If you ever manage to finish the code that is…
There is a finite number of integers in this context. For 32-bit it, it’s 4 billion or so (2^32).
And you could write a script to write the code for you
But that’s what TDD is for. If the test fails for 55, you just add a
return 56
, and then all is well.I let ChatGPT write it for me. The code and the test suite 💪
C++:
int i = 5; i ^= printf("The initial value of i is %d\n", i)^ printf("i=i+1; // this increments i\n")^ printf("Trigger very obscure FPU bug %c",(int)((float)8.5953287712*(double)8.5953287713-'?'))/10; printf("i has now been incremented by 1 : %d\n", i);
Output:
The initial value of i is 5 i=i+1; // this increments i Trigger very obscure FPU bug i has now been incremented by 1 : 6
I didn’t test other values but they’re probably OK.
I didn’t test other values but they’re probably OK.
Excellent work, thanks for the laugh.
Trying to avoid using any arithmetic operators, and sticking just to binary (extending beyond 16 bit unsigned ints is left as an exercise for the interested reader):
#!/usr/bin/perl # This increments $i my $i=1; print "Start: $i "; if (($i & 0b1111111111111111) == 0b1111111111111111) {die "Overflow";} if (($i & 0b0000000000000001) == 0b0000000000000000) {$i=(($i & 0b1111111111111110) | 0b0000000000000001);} else { if (($i & 0b0111111111111111) == 0b0111111111111111) {$i=(($i & 0b0000000000000000) | 0b1000000000000000);} if (($i & 0b0011111111111111) == 0b0011111111111111) {$i=(($i & 0b1000000000000000) | 0b0100000000000000);} if (($i & 0b0001111111111111) == 0b0001111111111111) {$i=(($i & 0b1100000000000000) | 0b0010000000000000);} if (($i & 0b0000111111111111) == 0b0000111111111111) {$i=(($i & 0b1110000000000000) | 0b0001000000000000);} if (($i & 0b0000011111111111) == 0b0000011111111111) {$i=(($i & 0b1111000000000000) | 0b0000100000000000);} if (($i & 0b0000001111111111) == 0b0000001111111111) {$i=(($i & 0b1111100000000000) | 0b0000010000000000);} if (($i & 0b0000000111111111) == 0b0000000111111111) {$i=(($i & 0b1111110000000000) | 0b0000001000000000);} if (($i & 0b0000000011111111) == 0b0000000011111111) {$i=(($i & 0b1111111000000000) | 0b0000000100000000);} if (($i & 0b0000000001111111) == 0b0000000001111111) {$i=(($i & 0b1111111100000000) | 0b0000000010000000);} if (($i & 0b0000000000111111) == 0b0000000000111111) {$i=(($i & 0b1111111110000000) | 0b0000000001000000);} if (($i & 0b0000000000011111) == 0b0000000000011111) {$i=(($i & 0b1111111111000000) | 0b0000000000100000);} if (($i & 0b0000000000001111) == 0b0000000000001111) {$i=(($i & 0b1111111111100000) | 0b0000000000010000);} if (($i & 0b0000000000000111) == 0b0000000000000111) {$i=(($i & 0b1111111111110000) | 0b0000000000001000);} if (($i & 0b0000000000000011) == 0b0000000000000011) {$i=(($i & 0b1111111111111000) | 0b0000000000000100);} if (($i & 0b0000000000000001) == 0b0000000000000001) {$i=(($i & 0b1111111111111100) | 0b0000000000000010);} } print "End: $i\n";
My favourite one is:
i -=- 1
This is actually the correct way to do it in JavaScript, especially if the right hand side is more than
1
.If JavaScript thinks
i
contains a string, and let’s say its value is27
,i += 1
will result ini
containing271
.Subtraction doesn’t have any weird string-versus-number semantics and neither does unary minus, so
i -=- 1
guarantees28
in this case.For the increment case,
++
works properly whether JavaScript thinksi
is a string or not, but since the joke is to avoid it, here we are.Every day, JS strays further from gods light :D
The solution is clear: Don’t use any strings
The near symmetry, ah, I see weve found the true Vorin solution.
Upvote for the stormlight archives reference.
The hot dog-operator
It looks kinda symmetrical, I can dig it!
C++ templates my beloved
#pragma pack(1) template <size_t i> struct increment; template <> struct increment<0> { char _plusone; constexpr static size_t value = 1; }; template <size_t i> struct increment<i> { increment<i - 1> _base; char _plusone; // this increments i constexpr static size_t value = sizeof(increment<i - 1>); }; template <size_t i> using increment_v<i> = increment<i>::value;
This could even be made generic to any integer type with a little more effort
Bonus : to use it without knowing i at compile-time :
template <size_t current_value = 0> size_t& inc(size_t& i) { if (i == current_value) { i = increment<current_value>::value; return i; } else { if constexpr (current_value != std::numeric_limits<size_t>::max()) { return inc<increment<current_value>::value>(i); } } } int main() { int i; std::cin >> i; inc(i); // this increments i std::cout << i << std::endl; return 0; }
Hope you’re not in a hurry
C# .NET using reflection, integer underflow, and a touch of LINQ. Should work for all integer types. (edit: also works with
char
values)// this increments i private static T Increment<T>(T i) { var valType = typeof(T); var maxField = valType.GetField("MaxValue"); var minField = valType.GetField("MinValue"); if (maxField != null) { T maxValue = (T)maxField.GetValue(i); T minValue = (T)minField.GetValue(i); var methods = valType.GetTypeInfo().DeclaredMethods; var subMethod = methods.Where(m => m.Name.EndsWith("op_Subtraction")).First(); T interim = (T)subMethod.Invoke( null, [i, maxValue]); return (T)subMethod.Invoke( null, [interim, minValue]); } throw new ArgumentException("Not incrementable."); }
Typing on mobile please excuse.
i = 0 while i != 1: pass # i is now 1
Reminds me of miracle sort.
Ah yes, the wait for a random bit flip to magically increment your counter method. Takes a very long time
The time it takes for the counter to increment due to cosmic rays or background radiation is approximately constant, therefore same order as adding one. Same time complexity.
Constant time solution. Highly efficient.
If you do it on a quantum computer, it goes faster because the random errors pile up quicker.
Finally, a useful real world application for quantum computing!
Unless your machine has error correcting memory. Then it will take literally forever.
Reminds me of http://www.thecodelesscode.com/case/21
I like to shake the bytes around a little
i = ( i << 1 + 2 ) >> 1
Wait, why does it multiply by 4? (apparently addition takes precedence over bitwise operations)
This is such hax
C:
int increment(int i) { return (int) (1[(void*) i])
However, if you wanna go blazingly fast you gotta implement O(n) algorithms in rust. Additionally you want safety in case of integer overflows.
use std::error::Error; #[derive(Debug, Error)] struct IntegerOverflowError; struct Incrementor { lookup_table: HashMap<i32, i33> } impl Incrementor { fn new() -> Self { let mut lut = HashMap::new(); for i in 0..i32::MAX { lut.insert(i, i+1) } Incrementor { lookup_table: lut } } fn increment(&self, i: i32) -> Result<i32, IntegerOverflowError> { self.lookup_table.get(i) .map(|i| *i) .ok_or(IntegerOverflowError) }
On mobile so I don’t even know if they compile though.
Using i33 for that extra umpf!
I guess that’s another way to avoid the overflow problem
Use bitwise operations to simulate an adder. Bonus points if you only use NOR
I decided to use NAND instead of NOR, but it’s effectively the same thing.
Scala:
//main @main def main(): Unit = var i = 15 //Choose any number here i = add(i, 1) //this increments i println(i) //Adds 2 numbers in the most intuitive way def add(a: Int, b: Int): Int = val pairs = split(a).zip(split(b)) val sumCarry = pairs.scanLeft(false, false)((last, current) => fullAdder(current._1, current._2, last._2)) return join(sumCarry.map(_._1).tail.reverse) //Converts an integer to a list of booleans def join(list: Seq[Boolean]): Int = BigInt(list.map(if (_) '1' else '0').mkString, 2).toInt //Converts a list of booleans to an integer def split(num: Int): Seq[Boolean] = num.toBinaryString.reverse.padTo(32, '0').map(_ == '1') //Adds 2 booleans and a carry in, returns a sum and carry out def fullAdder (a: Boolean, b: Boolean, c: Boolean): (Boolean, Boolean) = (NAND(NAND(NAND(NAND(a, NAND(a, b)), NAND(NAND(a, b), b)), NAND(NAND(NAND(a, NAND(a, b)), NAND(NAND(a, b), b)), c)), NAND(NAND(NAND(NAND(a, NAND(a, b)), NAND(NAND(a, b), b)), c), c)), NAND(NAND(NAND(NAND(a, NAND(a, b)), NAND(NAND(a, b), b)), c), NAND(a, b))) //The basis for all operations def NAND(a: Boolean, b: Boolean): Boolean = !a || !b
EDIT: replaced
Integer.parseInt
withBigInt(...).toInt
to fixNumberFormatException
with negative numbers.try it online here
Create a python file that only contains this function
def increase_by_one(i): # this increments i f=open(__file__).read() st=f[28:-92][0] return i+f.count(st)
Then you can import this function and it will raise an index error if the comment is not there, coming close to the most literal way
Any code which does not contain the comment “this increments i:” will produce a compile error and fail to run.
could be interpreted in python
writing code on my phone on the train with three minutes of time, let’s go and think of the worst possible solution!
int i = 1337; for (byte x = 0; x < 32; x++) { if (i & (1 << x) == 1) { i &= 0xFFFFFFFF ^ ( // dangit I'm out of time } else { i |= 1 << x; break; } }
Instead of a loop, you’d use 32 of these copy-pasted if statements and a goto :p
int toIncrement = ...; int result; do { result = randomInt(); } while (result != (toIncrement + 1)); print(result);
haha, bogoincrement! I hadn’t thought of that, nice :D
(shame it fails to compile though)
Your CPU has big registers, so why not use them!
#include <x86intrin.h> #include <stdio.h> static int increment_one(int input) { int __attribute__((aligned(32))) result[8]; __m256i v = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 1, input); v = (__m256i)_mm256_hadd_ps((__m256)v, (__m256)v); _mm256_store_si256((__m256i *)result, v); return *result; } int main(void) { int input = 19; printf("Input: %d, Incremented output: %d\n", input, increment_one(input)); return 0; }
I didn’t wake up expecting to hate someone today