As George Orwell wrote in 1984:

War is peace
Freedom is slavery
Ignorance is strength

Write a program or function that takes in one of the six main words from the Orwell quote and outputs its counterpart.


[input] -> [output]
war -> peace
peace -> war
freedom -> slavery
slavery -> freedom
ignorance -> strength
strength -> ignorance

No other input/output pairs are required.

You should assume the words are always fully lowercase, as above. Alternatively, you may assume the words are always fully uppercase: WAR -> PEACE, PEACE -> WAR, etc.

The shortest code in bytes wins.

  • 10
    \$\begingroup\$ Related :-) \$\endgroup\$ – xnor Jan 24 '17 at 22:04
  • 2
    \$\begingroup\$ @Dennis Yes. Either everything is lowercase, or everything is uppercase. \$\endgroup\$ – Calvin's Hobbies Jan 25 '17 at 2:26
  • 3
    \$\begingroup\$ Don't know if anyone can use this to compress their strings more (it didn't improve my score in Pip), but the initial letters of these words (w p f s i) are not found anywhere else in any of the words. An intriguing property. \$\endgroup\$ – DLosc Jan 25 '17 at 8:51
  • 13
    \$\begingroup\$ This is a doubleplusgood challenge \$\endgroup\$ – Jojodmo Jan 26 '17 at 6:28
  • 3
    \$\begingroup\$ Almost nobody likes this book. It's full of lies! Sad. \$\endgroup\$ – Peter A. Schneider Jan 26 '17 at 10:38

54 Answers 54


Ruby, 70 bytes

->s{a=%w(war freedom ignorance strength slavery peace);a[~a.index(s)]}

  1. Assign an array of strings war, freedom, etc. to a: a=%w(...)
  2. Find the index of the passed in parameter inside of a: a.index(s)
  3. Find the complement of the index. ~a.index(s) ex) ~0 == -1; ~1 == -2; ~-3 == 2
  4. Get the element at the complement: a[~a.index(s)]

Pyth, 54 bytes

@Jc"war peace freedom slavery ignorance strength"dx1xJ

Try it here.

Thanks to Leaky Nun for -2.


Python3, 204 bytes

def O(W):
  return R

A bit longer than I hoped, but hopefully interesting enough.

Try it online! (all testcases included)


Alphabet = "cenayhglmodrtvifspw" #Alphabet to convert strings to numbers and vice versa

def StringToNumber (s): #Identify the word by the second letter
  return Alphabet.find(s[1]) 

def NumberToString (O):
  while (O>0):
  return res

def F(x): # the 'magic' function. Note that we can use floats with fewer decimals due to rounding
 return 177638 + (172739/3 + (1074106505/264 + (-(32699060621/7392) + (1986769150133/22176 - (2050733259611*(-7 + x))/332640)*(-8 + x))*(-12 + x))* (-1 + x))*(-4 + x)

def Orwell(s):
 return NumberToString(round(F(StringToNumber(s))))

Since most answers seem to be literally writing the words or looking them up in a dictionary to output them, I was interested in not doing that, as that could be an improvement for most non-golfing languages.

The basic idea is simple: change the input into a number x, calculate F(x) and change that back into a word.

Of course, F(x) is chosen such that the number corresponding to "war" maps to the number for "peace", etc. This is done using Lagrange interpolation, which gives the unique minimum degree polynomial such that F(x_1)=y_1, F(x_2)=y_2, etc. To reduce the constants in the formula a bit, the characters in the alphabet are placed such that characters in the end of the longer words come first. The first character in the alphabet cannot be at the end of a word, since this means we have to distinguish trialing zeros, which we cannot (int("0039")==int("39")).

Still, the formula is quite big. This approach would probably work better if the strings were over a smaller alphabet, as that reduces the constants in F.

  • \$\begingroup\$ Not sure if this is considered a 'serious contender'. According to this, other methods are ok even if they have a low score, but the comments imply that worse than naive scores are not acceptable. \$\endgroup\$ – Discrete lizard Apr 30 '17 at 21:12

Axiom, 155 bytes

t:Table(String,String):=table();a:=["war","peace","freedom","slavery","ignorance","strenght"];for i in 1..#a-1 by 2 repeat(t(a.i):=a.(i+1);t(a.(i+1)):=a.i)

test and result

(3) -> for i in a repeat output [i,t(i)]

J, 61 bytes

-&.((cut': war freedom ignorance strength slavery peace')i.<)

: fills the 0th position, so the first element corresponds to negative 1st (last), and so on. Lookup the word and negate the index.

Try it online!


Stax, 31 bytesCP437


37 bytes when unpacked,


Run and debug online!


`j<r:8GGme*6k{"TQH>C;q)Jc4%&`            Compressed string literal for
                                             war freedom ignorance strength slavery peace
                             j           Split on spaces
                              c,]I       Find index of input
                                  Nv     Negate it and minus one
                                    @    Get the element at index
                                         Implicit output

Clojure, 98 bytes

Direct port of @Arnauld's JavaScript answer.

#((clojure.string/split"freedom,,war,,strength,,slavery,peace,ignorance"#",")(rem(int(nth % 1))9))


(defn war [word]
  ; Create a list of strings by splitting on commas, and "get" from the resulting list
  ((clojure.string/split "freedom,,war,,strength,,slavery,peace,ignorance" #","
     ; Calculate the index to get (see the original answer for details)
    (rem (int (nth word 1)) 9))))

C 211 bytes

#define S !strcmp void f(char *s){*a[]="WAR","PEACE","FREEDOM","SLAVERY","IGNORANCE","STRENGTH"};printf("%s",S(s,a[0])?a[1]:S(s,a[1])?a[0]:S(s,a[2])?a[3]:S(s,a[3])?a[2]:S(s,a[4])?a[5]:S(s,a[5])?a[4]:"\0");

Assuming inputs in caps only.

Ungolfed version:

#define S !strcmp

void f(char *);

int main(int argc, char *argv[])
void f(char *s)

Can definitely be shortened in someway!


Pip, 57 55 bytes

(aN_FI"warpeace freedomslavery ignorancestrength"^s)Rax

Saved 2 bytes by adapting MickyT's clever R answer. Try it online or verify all test cases.


                   a is cmdline arg; s is space (implicit)
      "..."^s      Split string on spaces to create three-item lookup table
    FI             Filter on this function:
 aN_                 a is a substring?
(            )Rax  In matching lookup entry, replace a with empty string and autoprint

SpecBAS - 123

1 DIM a$="war","peace","freedom","slavery","ignorance","strength"
2 INPUT b$: n=SEARCH(a$() FOR b$): ?a$(IIF(ODD n,n+1,n-1))

Finds the index of the input string.

Inline IF checks if that is odd to print either the string after or before that position.


JavaScript, 80 bytes

Somewhat similar to this JavaScript answer (but developed totally independently), this program reads the input as a base-30 number, takes the parsed value modulo 7, and uses that result as an index to fetch the corresponding value from an array. war cannot be parsed as a base-30 number, so it produces NaN, which falls back to peace outside the array.

  • \$\begingroup\$ Just wrote a solution, w=>(a="war slavery ignorance strength freedom peace".split(" "))[5-a.indexOf(w)], that is also 80 bytes! \$\endgroup\$ – FlipTack Jan 28 '17 at 18:42
  • \$\begingroup\$ @FlipTack Then is think you can beat mine by doing .split(0)! \$\endgroup\$ – apsillers Jan 28 '17 at 22:19
  • \$\begingroup\$ You're right, posted it :) \$\endgroup\$ – FlipTack Jan 29 '17 at 16:30

Java 8, 183 bytes


s->java.util.Arrays.stream(new String[]{"pewar","wapeace","slfreedom","frslavery","stignorance","igstrength"}).filter(t->t.startsWith(s.substring(0,2))).findFirst().get().substring(2)

Ungolfed with test program:

public class WarIsPeaceFreedomIsSlaveryIgnoranceIsStrength {

  public static void main(String[] args) {
    for (String str : new String[] { "war", "peace", "freedom", "slavery", "ignorance", "strength" }) {
      System.out.print(" = ");
      System.out.println(f(s -> java.util.Arrays.stream(
        new String[] { "pewar", "wapeace", "slfreedom", "frslavery", "stignorance", "igstrength" }).filter(
          t -> t.startsWith(s.substring(0, 2))).findFirst().get().substring(2),

  private static String f(java.util.function.Function<String, String> function, String input) {
    return function.apply(input);

This function is nested lambdas with streams. It takes an array of strings where the first two characters of the string acts as a map key, matching the input, while the remainder of each string is the map value, the output. It finds the string matching the given input and returns the string that matches it.

Program output:

war = peace
peace = war
freedom = slavery
slavery = freedom
ignorance = strength
strength = ignorance
  • 1
    \$\begingroup\$ Try "pewar wapeace slfreedom frslavery stignorance igstrength".split(" "). And you can use Stream.findAny. \$\endgroup\$ – Jakob Sep 4 '17 at 16:11

QBIC, 82 bytes

;?mid$(@ignorancefreedom  peace    strength slavery  war      `+B,instr(B,A)+27,9)

This is a quite literal translation of my QBasic answer. It's a bit shorter because QBIC handles (some of) the QBasic boilerplate.


SOGL, 23 bytes (non-competing)



7                        push 7
 "ņVυr11<╝⅔`▒τ¶‘         push "ignorance strength war peace freedom slavery"
                @Θ       split on spaces
                  ,W     get the index of input in the array (e.g. war)
                         stack: [7, [ignorance,strength,war,peace,freedom slaver], 3]
                    h    swap the 7 and array
                         stack: [[ignorance,strength,war,peace,freedom slaver], 7, 3]
                     -   subtract
                         stack: [[ignorance,strength,war,peace,freedom slaver], 4]
                      w  get the nth item from the array (e.g. peace)

non-competing because somehow I didn't have a split on function. Dunno how that happened.

Would be 22 bytes with a split on space command but this is a more realistic score.


8th, 96 bytes

: f ["ignorance","strength","war","peace","freedom","slavery"] swap ' s:= a:indexof 1 bxor a:@ ;

Usage and output

ok> "war" f . drop

Ungolfed version (with comments)

: f \ s -- a s
  ["ignorance","strength","war","peace","freedom","slavery"] \ Push the array on the stack
  swap            \ Put input string on TOS 
  ' s:= a:indexof \ Get the index of the input string in the array
  1 bxor          \ XOR the index with 1
  a:@             \ Push on the stack the element in the array at that index

///, 106 bytes


Try it online!

Since /// has no other way of taking input, it can be hard-coded. The input goes at the very end of the program.

Pretty simple, it takes one word, and replaces it with another, but the replacement has an @ sign in it. That is because if there was no @ sign, the program would get stuck replacing one word with the same word. The @s are removed at the end of the program.


C(bcc 32 bit int), 124 bytes

g(int*a){int*b[]={"war","peace","freedom","slavery","ignorance","strenght"},i=0;for(;i<6&&*b[i++]-*a;);return b[i%2?i:i-2];} 

g:Strings->Strings would return the next b[i+1] or the precedent b[i-1] pointer value based on i%2


Japt, 38 37 bytes


Try it


Tcl, 114 bytes

set L {war peace freedom slavery ignorance strength}
puts [lindex $L [expr [set i [lsearch $L war]]%2?$i-1:($i+1)%7]]

                                         Not accounting "war" word as it is input parameter

Try it online!


q/kdb+, 65 61 bytes






Built a dictionary of keys->values, lookup user input in the merged dictionary:

{(x,y)!y,x}[`war`freedom`ignorance;`peace`slavery`strength]`$ / solution
{         }[                      ;                       ]   / lambda with implicit x and y
            `war`freedom`ignorance                            / the x
                                   `peace`slavery`strength    / the y
       y,x                                                    / append x to y
 (x,y)                                                        / append y to x
      !                                                       / create dictionary keys!values
                                                           `$ / cast input from a string into a symbol

Clojure, 98 (?) bytes

(def m '("war""peace""freedom""slavery""ignorance""strength"))(apply hash-map(concat(reverse m)m))

The second expression is a hash-map which can be called as though it were a function to obtain the desired result, but I'm not sure this exact line of code counts when you have to go in there and add a parenthesis in the middle to actually use it. Anyhow this manages to be marginally shorter than just writing the whole map out manually by taking advantage of how hash-map reads items in a sequence as alternately keys and values by reversing the sequence and concatenating it to itself to provide both forward and backward mappings.


ink, 111 bytes

LIST d=war,freedom,ignorance,peace,slavery,strength

Try it online!

Called as ->n("war")->.

If taking one of the list values rather than a string as input is acceptable (I feel like it probably shouldn't be), there's a 79-byte solution:

LIST D=war,freedom,ignorance,peace,slavery,strength

Try it online!


05AB1E, 29 bytes


Try it online!


C, 137 101 98 132 characters

counted with escaped characters as 1

void i(char*i){char*s="\7\4\23c\25e\25\36\4\23\1\35\24\0\32\23\34\12\34\6\32\13e";for(s+=i[3]&4?i[4]&2?14:6:0;putchar(*i++^*s++););}

Try it online

  • 1
    \$\begingroup\$ Any idea why tio.run/nexus/… doesn't work? Replacing puts("") with putchar(10) somehow fixes the issue. \$\endgroup\$ – Dennis Jan 28 '17 at 18:35
  • \$\begingroup\$ It's likely because I'm cheating a little and relying on the layout of the input strings in the main function. I was hoping someone would pick up on that ;) \$\endgroup\$ – Ahemone Jan 29 '17 at 11:33
  • 1
    \$\begingroup\$ You're printing extra null characters, and your byte count is incorrect. \$\endgroup\$ – Jakob Sep 4 '17 at 16:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.