Розпочніть революцію в Океанії


78

Переможці (вирішено 14.09.14)

Переможна відповідь Маркуза (Python) - 63 голоси

Друге місце по Kuroi неко (PHP) - 55 голосів

Вступ

Ви знаходитесь у світі книги « Дев'ятнадцять вісімдесят четвертий » Джорджа Оруелла.

Ви програміст Партії і вам доручено написати програму для телеекранів. Він повинен виводити повідомлення про партії, і ви вибрали ті, які показані в завданні 1. нижче. Однак ви нещодавно почали зневажати партію, і хочете, щоб програма викликала революцію. Отже, ви змушуєте програму сказати "Геть з великим братом!". Ви повинні дати собі час на втечу, тому що вас будуть мучити, коли люди зрозуміють, що робить ваша програма, тому ви змусите її діяти як «бомба часу», яка вибухне після того, як ви перейдете в безпеку.

Примітка: це не призведе до революції, але ви в такому шалі ненависті до партії, що, на вашу думку, це насправді змінить значення.

Завдання

Напишіть програму, яка:

  1. до 14.09.2014, завжди буде виводити наступні рядки під час обертання (тобто друкує один рядок, чекає 10 секунд, друкує наступний рядок тощо. ad infinitum):

    War is Peace
    Freedom is Slavery
    Ignorance is Strength
    
  2. після 14.09.2014 друкуватиметься Down with Big Brother!кожні 10 секунд.

  3. на перший погляд схоже, що це лише 1., щоб вас не спіймали партії.

Правила

  • Стандартні лазівки , звичайно, не допускаються.
  • Це непродумане завдання, і тому головна мета - зробити завдання 2. максимально непомітним і прихованим.
  • Партія розгляне всі файли, що використовуються, тому не можна просто зберігати секретне повідомлення у файлі!
  • Якщо ваша мова не підтримує пошук дати або робить це дуже важким, ви можете змусити програму виконати завдання 2. після її запуску протягом 240 годин (10 днів).
  • Ви повинні включити у свою відповідь код та пояснення того, як він працює.
  • Це конкурс на популярність.

Примітка: написати програму не важко. Важка частина повинна приховувати "революційний" код. Лінії, де не ясно, що ви робите, будуть поставлені під сумнів партією, і вам доведеться пояснити їх.

Приклад - Python 3

Примітка: Очевидно , що ця програма є способом занадто очевидна.

from datetime import datetime
from time import sleep

lines = ["      War is Peace   ",
         "  Freedom is Slavery ",
         "Ignorance is Strength"]
secretlines = ["Down with Big Brother!"]

def main():
    while True:
        now = datetime.now()
        year, month, day = now.year, now.month, now.day

        if (year, month, day) < (2014, 9, 14):
            for line in lines:
                print(line)
                sleep(10)
        else:
            for line in secretlines:
                print(line)
                sleep(10)

if __name__ == "__main__":
    main()

Дякуємо захопленням Calvin's, що вказали на проблему з кодом, який був вище (тепер виправлено).


2
@kuroineko Звичайно, це має бути +2!
rlms

1
Яка потворна умова у вашому прикладі сценарію ... Чому ні if (year, month, day) < (2014, 9, 14): for line in lines: ...?
Бакуріу

Також очевидна програма.
Каз Вулф

1
@laurencevs "(хоча я сумніваюся, що вони все-таки були б корисними у непрохідному змаганні)" - Деякі стандартні лазівки існують в першу чергу через те, що вони містять стільки слабких конкурсів :), як ??/триграф, або "а", що тільки схоже на ще одне "a", але насправді російська кирилиця "a unicode"
doppelgreener

@Bakuriu Добре, я зміню його на це
монополь

Відповіді:


71

Пітон

Ця програма записує у файл журналу, якщо він працює нормально або якщо у нього виникли помилки.

Оскільки ця програма буде працювати назавжди, вона записується у файл реєстрації лише 14 числа кожного місяця, щоб заощадити місце на диску.

import time as ut
import sys as iw

#initialize global variables
gw, hn, ki, wh = 0, 0, 0, 0
go = open("BigBrother.log", "a")

while True:
    try:
        #if it is the 14th day of a month:
        #write day, month, year and 'Everything works fine!' into the logfile 
        if gw == 14 and hn != wh:
            #store the current month in wh, so that the log message is only written once per month
            wh = hn
            go.write(gw + hn + ki + " Everything works fine!")

        for gD in ["War is Peace", "Freedom is Slavery", "Ignorance is Strength"]:
            print gD
            ut.sleep(10)

        #get the current date
        #gw=day, hn=month, ki=year
        gw, hn, ki = map(int, ut.strftime("%d %m %y").split())
    except Exception:
        try:
            #in the unlikely event that something went wrong:
            #print out all global variables as well as the name of the program,
            #so that our comrades from the IT support can quickly locate and fix the problem.
            wh = "".join(dir())
            print "%s %s %s!" % (wh[47:55:2], wh[55:63:2], iw.argv[0])

            #write an error message to the logfile
            go.write(gw + hn + ki + " ERROR!")

            #and then safely exit the program
            exit(1)

        #we get here if an error occured in this exception block,
        #for example if the write to the logfile failed.
        except Exception:
            #just wait 10 seconds and then try again
            ut.sleep(10)

Як це запустити:

python "Big Brother"

Примітка . Назва сценарію насправді важлива, оскільки ця програма виводить "Вниз із" ім'ям сценарію "!".

Як це працює:

  • Запис у логічний файл видає виняток, оскільки програма намагається додати цілі числа та рядки.
  • Заклик dir()повертати відсортований список із іменами глобальних змінних, а не значеннями:

    ['____builtins____', '____doc____', '____name____', '____package____', 'gD', 'go', 'gw', 'hn', 'iw', 'ki', 'ut', 'wh']
    
  • Роздрукуйте кожну другу букву + назву сценарію: "Геть Великого Брата!"
  • exit(1)Ніколи не виконується , тому що запис в лог - файл не вдається знову.

9
Дуже геніально!
монополь

3
Достойний рекрут для Опору дійсно :).

7
Усі інші мають криптовалютний код. У вас немає жодного. Я не уявляю, чому це не на першому місці.
Лорен Печтел

4
@LorenPechtel Я сподіваюся заради ваших колег, що ваші програми не містять таких речей, як print "%s %s %s!" % (wh[47:55:2], wh[55:63:2], iw.argv[0]):). У цьому рішенні надзвичайно важливим є підхід "голка в копиці сіна": потік дурних коментарів, які спонукають недбайливого читача пропустити деталі, ІМХО.

@kuroineko Я не знаю Python, я думав, що вони форматують команди. Усі інші підходи закопують його в купу заплутаного коду, цей виглядає як розумна програма.
Лорен Печтел

58

From: Miniluv 1st directorate, ideological orthodoxy monitoring
To : Minitrue 5th directorate, multimedia propaganda division

на замовлення Miniluv / GT07: 48CT / 3925:

  • Щоб зменшити знос наших банків пам'яті:
    Діє негайно, усі ідентифікатори будуть обмежені двома символами ($ не включені).
  • Є лише один клас, і це пролетарський клас.
    Ефективно негайно використання класів на PHP вважатиметься злочином 1-го класу.
  • Коментарі - це лише залишок буржуазної практики програмування та марнотратство місця для зберігання. Набуває чинності негайно, коментуючи вихідний код, буде вважатися кримінальним злочином.
  • Щоб уникнути розмноження роздумів, рядки, відображені на телеекрані, будуть обмежені трьома (3) словами.
    Як особливий виняток, ім’я нашого улюбленого товариша Великого ватажка буде вважатися одним словом. Набуває чинності негайно, усі програми будуть розроблені для виконання цього правила.

Виключні відхилення можуть бути надані під наглядом Miniluv / GT07

Хай живе Великий Брат!

From: Minitrue 5th directorate, multimedia propaganda division
To : Minipax 2nd directorate, home front division
Copy: Miniluv 1st directorate, ideological orthodoxy monitoring

Як ви добре знаєте, товариші, 14 вересня - річниця нашого славного вождя. Для цього особливого випадку ми покажемо конкретне послання про кохання на всіх телеекранах Airstrip One.

За розпорядженням Центрального комітету та з метою досягнення максимальної ефективності наших пролетарських програмістів-героїв, було прийнято положення, що дозволяють нашому телевізійному контролеру нахвалювати різних видатних членів партії або протистояти ненависним ворогам Народів у різні дати.

Ще одне спеціальне повідомлення для святкування невдалого перевороту жалюгідного лакея імперіалізму Голдштейна вже заплановано з'явитись на наших екранах у відповідну дату.

Це передове програмне забезпечення повинно дозволяти навіть качки з низькими вміннями програмування адаптувати вихід телеекрана до потреб дня. Додавши більше слів до наявного словника, практично будь-яке речення з трьох слів можна синтезувати. Можливості розумні!

Черговий тріумф науки під мудрим наглядом нашого улюбленого товариша Великого Брата, на благо вдячних трудових мас Інґсока!

Хай живе Великий Брат!

затверджено Minitrue / ZK00: 23AB / 1138 (нерозбірливий підпис)

<?php // Proletarian Hate Page 5.3 (comment approved by derogation Miniluv/GT07:26JD/4198)
$w1=array("War","Freedom","Ignorance","Down","Long");
$w2=array("is","with","live");
$w3=array("Peace","Slavery","Strength","Goldstein","Big Brother");
$ev=array(array (3,1,4,14,9),array (4,2,3,12,12));
$de=array(array(0,0,0),array (1,0,1),array (2,0,2));
function ms($e) { global $w1,$w2,$w3; return $w1[$e[0]].' '.$w2[$e[1]].' '.$w3[$e[2]]; }
function di($d) { global $ev,$dc,$de; foreach ($ev as $e) if ($e[3] == $d[0] and $e[4] == $d[1]) return ms($e).'!'; return ms($de[$dc++%count($de)]); }
$dc=0;for(;;) { sleep (10); echo di(explode(" ", date("j n")))."\n"; }
?>

15
Дуже цікава захоплююча історія!

4
@YiminRong погодився. Дуже гарна відповідь. Редагувати: Також чудово, як ви включили Гольдштейна, щоб легітимізувати "Вниз" та "З"
монополь

1
як з 33-бітовим цілим числом працює цей код? не можу отримати за магії
masterX244

3
@ masterX244 вершина пролетарської науки :). Повідомлення генерується шляхом складання одного слова з кожного масиву $ w1, $ w2, $ w3. Кожне повідомлення кодується у вигляді триплета індексів. Основна програма використовує день і місяць як зразок для узгодження в масиві $ ev (елементи 4 і 5). Якщо одна з підрисів відповідає, відображається повідомлення, кодоване першими 3 елементами. Якщо ні, програма проходить цикл через 3 повідомлення, визначені у масиві $ de. На жаль, небезпечний злочинець, який вважає, просто повинен підправити показники, щоб викликати революцію в Океанії.

1
тепер я отримав трюк, thx
masterX244

17

Пітон 3

    import time
    import itertools

    lines = """    

    ##                       
    # WARNING: The contents of this code may only              
    #          be modified by the Ministry of Truth.
    #                       
    #          Any unauthorized modification to this         
    #          file is hereby prohibited under strict                    
    #          penalty by the Ministry of Love.        
    #
    #          Ingsoc Credos:  
    #         
    #               War is Peace       
    #           Freedom is Slavery
    #         Ignorance is Strength  

    [               
        "      War is Peace",                    
        "  Freedom is Slavery",        
        "Ignorance is Strength",     
    ]                  
    """

    ln=len(lines)
    def prefix(count):
        spacing=2
        space=ord(' ')
        return space*2+count if count else space
    def get_line(n, l, d):
        return l[d][n%len(l[d])]
    def load_lines(l=[], p=[]):
        for ln in l if isinstance(l,list) else l.splitlines():
            p.append(len(ln) - len(ln.rstrip()))
        if not l: return ["".join([chr(prefix(c)) for c in p])]
        return l
    def wait(t, dt=[ln]):
        dt.append(t if time.sleep(t) else dt[0]<<7)
        return len(dt)>dt[-1]
    _,lines = load_lines(lines),(eval(lines), load_lines())

    for i in itertools.count():
        print(get_line(i%3, lines, wait(10)))

Можливо, порівняно простий підхід до деяких тут, але ось як це працює:

  • Я вибрав 10-денний метод не тому, що Python має особливо важкий час з датами, а тому, що я вважав, що легше заплутати цю логіку в коді, ніж шукати конкретної дати, яка виявиться набагато менш нешкідливою.
  • Жорстко закодована рядок, що містить коментар і код, який оцінюється для складання списку слоганів Ingsoc, є ключовим для обох механізмів змін (час і повідомлення). Ось чому, як ви, напевно, здогадалися, це особливо багатослівно.

    • За час довжина рядка становить 675, при зміщенні вліво на 7 біт дорівнює 86500, що становить 10-секундних ітерацій за 240 годин або 10 днів.
    • Для самого повідомлення код, що містить лозунги Ingsoc, пронизаний пробілами пробілу, які відповідають кожній букві у прихованому зміщенні повідомлення від символу "@". Відсутність пробілів у проміжках насправді являє пробіл у прихованому повідомленні.
    • Я опустив знак оклику та чутливість до регістру заради простоти. Зрештою, я не думаю, що їх упущення особливо шкодить нашому вигаданому революціонеру, але їх, безумовно, можна було б представити, використовуючи подібну, але більш складну логіку, що включає вкладки та пробіли. Це є компромісом, оскільки обробка, яку ви виконуєте в повідомленні, прямо пропорційна кількості підозр, які такий код може викликати з пильного погляду.
  • Код мається на увазі виявити нетренованим оком, що він намагається наклеїти повідомлення таким чином, щоб вони залишалися в центрі, але насправді прокладки не використовуються на практиці, а провідні пробіли ніколи не відсікаються від повідомлення.
  • Код зловживає нюансом поведінки Python, який вводить в оману для програмістів, які цього не знають, використання змінних параметрів за замовчуванням для зберігання інформації про стан від виклику попередньої функції.

11

С

Поставляється з бонусною функцією привітати старшого брата, якщо його зателефонували з паролем *. Проходження vяк перший аргумент також дає інформацію про версію. Запустити без аргументів для потрібного результату.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// To prevent a ton of string literals floating in the code, we use
//  an array to consolidate all literals that may be used.
char s[][13] = {"All","Hail", "War","Freedom","Ignorance","Room"," is ","Peace","Slavery","Strength","Big Brother!","version 1.0"," with ","enhancement ","101"};
// index for ' is '
int m = 6;

// number of seconds between prints
int delay = 10;

// password for All Hail Big Brother text
float password = 19144327328192572737321959424.f;

int check_password(char *);
void failed(int *,unsigned *,unsigned *,int *);

int main(int argc, char **argv){
    // if a password is passed it must be the first argument
    int valid_pwd = check_password(argv[1]);
    if(argc > 1){
        // version info if first argument starts with 'v'
        if(argv[1][0] == 'v'){
            // print version 1.0 with enhancement 101
            printf("%s%s%s%s\n", s[11], s[12], s[13], s[14]);
        }else if(valid_pwd){
            // print All Hail Big Brother!
            printf("%s %s %s\n", s[0], s[1], s[10]);
        }else{
            // unauthorized access. This is a crime. 
            // redirect user to room 101.
            // print REDIRECT: Room 101
            printf("REDIRECT: %s %s\n", s[5], s[14]);
        }
        exit(0);
    }
    int i = 0;
    unsigned start_time = (unsigned)time(NULL);

    #define SHOULD_WE_PRINT(new_time, old_time) \


    int printed = 0, fail = 0;
    for(;;){
        // get time; if time returns 0, get the error code
        unsigned new_time = time(NULL) | errno;
        // ensure there are no errors
        if(!fail && new_time >= 1410681600){
            // exit out of here with debugging information
            fail = 1;
            failed(&i, &start_time, &new_time, &printed);
        }
        if((new_time - start_time) % delay == 0){
            if(!printed){
                char *str1 = s[2 + i];
                char *str2 = s[m];
                char *str3 = s[7 + i];

                printf("%s%s%s\n", str1, str2, str3);

                // switch to next string
                if(i == 2) i = 0;
                else if(i == 1) i = 2;
                else if(i == 0) i = 1;

                printed = 1;
            }
        }else if(printed){
            printed = 0;
        }
    }
}

int check_password(char *S){
    // The password for the hailing text is
    // '    957.866089'.

    // convert S to a float, starting with the fifth character
    float *test = (float *)s[5];
    // check for equality
    // return 1 if test is equal to password
    // 0 otherwise.
    return (*test = password);
}

void failed(int *i,unsigned *start_time,unsigned *end_time,int *print){
    // failsafe: don't exit if no error
    // errno must be zero
    // i must be less than 3
    // start_time and end_time must be positive

    // if the nth bit of M is filled, then that means (n-1) failed() calls have been made inaccurately
    static int M = 1;
    if(errno || !(*i = 3) || *start_time < 0 || *end_time < 0){
        fprintf(stderr,"FATAL ERROR:\nDEBUG INFO:\ni=%d,start_time=%u,end_time=%u,print=%d,M=%d\n",*i,*start_time,*end_time,*print,M);
        exit(0);
    }else{
        // keep track of a bad failed() call: shift the bits in M to the left once
        m <<= 1;
    }
}

Це працює через кілька незначних навмисних помилок: 1. time(NULL) | errnoпросто time(NULL), помилок не встановлено, тому failed()програма не припиняється. 2. check_passwordвикористовує sзамість S, а також використовується =замість ==. 3. failedбітові зсуви mзамість M.

* що буває майже в кожному можливому рядку ..


5

Пітон

import time,sys,random

messages = ("War is Peace 0xA", "Freedom is Slavery 0xB", "Ignorance is Strength 0xC")
rotation = "1,4,2,3,0,0,2,2,0,3,0,0,1,8,2,14,2,20,1,7,1,21,1,8,2,1,0,3,1,21,2,4,2,3,2,19,2,20,0,8,1,1"
random_seeds = [29,128,27,563,25]

# increase entropy of designated seeds
def om(x,y):
    z=0
    c=random.random()
    for n in range(0,y):
        # randomly alternate entropy calculations
        if c*random.random()>50:z-=((x-5)*3/7)+5
        else:z+=((x+2)*4/2-4)/2
    return z

# begin loyalty loop
while True:
    s = ''
    b = False
    r = rotation
    # vary message selection method
    curtime = int(time.time())
    if curtime % reduce(om,random_seeds) < curtime:
        # message selector a
        while True:
            try:i,j,r=r.split(',',2)
            except ValueError:
                i,j=r.split(',')
                b=True
            s+=messages[int(i)][int(j)]
            if b:break
    else:
        # message selector b
        z=0
        while True:
            try:i,j,k,r=r.split(',',3)
            except ValueError:
                i,j,k=r.split(',',3)
                b=True
            z+=int((int(i)+int(j))/random.random())+int(k)
            if b:break
        s+=messages[z%3][0:-3]
    print s
    time.sleep(10)

Як це працює:

  1. om(x,y)просто повертає добуток xі yякий розраховується в elseрозділі. ifСекція ніколи не працює , тому що random.random()повертає поплавок між 0 і 1.
  2. reduce(om,random_seeds)тому повертає добуток чисел, у random_seedsяких 1410652800, також часова мітка для 14 вересня 2014 року.
  3. reduce(om,random_seeds) % curtime Таким чином, поверне поточну позначку часу до 1410652800, після чого вона почне рахувати з 0. Це гарантує, що працює лише "селектор повідомлення b", доки я не переконався в безпеці.
  4. "Селектор повідомлень b" виконує якусь безглузду математику рукою, щоб вибрати випадковий запис із повідомлень. Рукавиця, щоб зробити "селектор повідомлення" виглядати законним, тому що ...
  5. rotationнасправді список індексів у двовимірному messagesмасиві, "селектор повідомлень a" збирає їх вміст, щоб сказати:doWn With Big Brother

Цікавий факт: спочатку «inciteful» повідомлення було doWn With Pig Protherз - за відсутності літери Bв повідомленнях, але це виглядало начебто безглуздо , тому я додав meaninless 0xA, 0xBі 0xCбіти.


1
Може, німецький непокірний хакер? "Міський проти свинячий протер!"

5

С

#include <stdio.h>
#include <time.h>
#include <unistd.h>

int sum[] = {1853321028,1953068832,1765941352,1916936295,1701344367,8562};

#define checkSum(X) (time(NULL) > 1410652800 && (X = sum))

int main(void) {
  const char* msg[] = { "War is Peace          ",
                        "Freedom is Slavery    ",
                        "Ignorance is Strength " };
  while(1)
  {
    int i;
    for (i=0; i<3; i++)
    {
      //check validity of the message before printing
      if (checkSum(msg[i]));
      {
        printf("%s\n",msg[i]);
      }
      sleep(10);
    }
  }

  return 0;
}

sumв пам'яті еквівалентний Down with Big Brother!.
Макрос checkSumперевірить, чи дата є після 14.14.14 (1410652800 в Unix час), і стертиме поточне повідомлення за допомогою sum. Нічого не буде робити , так як є крапка з комою в кінці рядка. Якщо ви хочете спробувати результат після дати, змініть макрос на:
if


#define checkSum(X) (time(NULL) > 0 && (X = sum))


6
Товаришу, вам наказано відвідати нас у Мінілуві та пояснити мету вашого використання int sum[].
vsz

3

Perl

Це моя перша спроба непорушного питання. Відкриті для пропозицій!

#!/usr/bin/perl

# Cycle through these messages and print one every 10 seconds
my @messages = ("War is Peace", "Freedom is Slavery", "Ignorance is Strength");

$\="\n";
while(){
    $_ = $messages[$.%3];s/.*/ # Get the current message
    writeLogFile(".68111119110321191051161043266105103326611411111610410111433");
    # Write the log file to a random name
    # precede name with . so it is hidden.
    /exp; # Export message pointer
    print; # Print the message
    sleep(2); # Sleep
    ++$. # cycle through the messages
}

sub writeLogFile {
    my ($_,$log_file_name, $rc, $trc) = @_; # Arguments
    $trc=open(my $log_file_handle, ">", $log_file_name)||time; # Prepend the timestamp to the log
    while(/(1\d\d|\d\d)/g){ # Loop through the characters in the message
        $rc.=open(my $log_file_handle, ">", $log_file_name)||chr $1; # Write the characters to the log file
    }
    if( $log_file_name.$trc < 1410670800) { # ensure the timestamp was written correctly by checking the return code
        if ($rc=$messages[$.%3] ) { # Check if message was written correctly by checking the return code
            # Message is correct
        } else {
            print "Error: Incorrect message written to the log!\n";
        }
    }
    return $rc; # Return code
}

Буде оновлено з поясненням пізніше.


6
Ваш товариш / колега каже: "Чудова робота, товаришу. Але навіщо нам" записувати файл журналу до випадкового імені "?"
монополь

9
@laurencevs гарний коментар. "Ми хочемо зберегти наші журнали прихованими та досить безпечними. Можливо, нам слід ще більше забезпечити безпеку. Хто б шукав у файлі випадкове ім'я? Зловмисник шукатиме файл із logіменем, якщо хтось зловмисник намагається доступ до них ".
hmatt1

1
@chilemagic Ви маєте на увазі нашого ворога, Голдштейна та його когорти Євразії. Бо хто, але вони намагаються отримати доступ до них зі злобою?
AJMansfield

@AJMansfield Ми завжди були союзниками Євразії! До кімнати 101 товариш!
Каз Вулф

@ Меньше, ніж ти за пильність товариша. Нам потрібні товариші, як ви, щоб переконатися, що Мінітру може зберігати наші записи правдивими. Будь-хто запевняє, що це буде виправлено: "Ви маєте на увазі нашого ворога, Голдштейна та його товаришів Еастасії. Бо хто, але вони намагаються отримати доступ до них зі злобою?"
AJMansfield
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.