понедельник, 17 февраля 2014 г.

Python: Числовые ребусы

Программка для разгадывания числовых ребусов. Методом грубой силы (т.е. простым перебором).

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import sys

#equation = u'удар+удар==драка'
#equation = u'кошка+кошка+кошка==собака'
#equation = u'кто+умён+тот==силён'
#equation = u'где*где-всюду==везде'
equation = u'масло+ноль==омлет'

def replace_all(text, srch, repl):
    for i in range(0, len(srch)):
        text = text.replace(srch[i], repl[i])
    return text

letters = []

for l in equation:
    if l not in ('+', '=', '-', '*'):
        if l not in letters:
            letters.append(l)

tops, counters = [], []
for i in range(0, len(letters)):
    tops.append(10 - i)
    counters.append(0)

canExit = False
while(not(canExit)):

    numbers = ['0','1','2','3','4','5','6','7','8','9']
    substs = []
    for i in range(0, len(tops)):
        substs.append(numbers[counters[i]])
        del numbers[counters[i]]

    text = replace_all(equation, letters, substs)
    try:
        if eval( text ):
            print text
    except:
        None

    N = 0
    inc = 1
    while (N < len(counters) and inc > 0):
        counters[N] += inc
        inc = 0
        if (counters[N] == tops[N]):
            counters[N] = 0
            inc = 1
            N += 1

    canExit = True
    for i in range(0, len(tops)):
        canExit &= (counters[i] == tops[i]-1)

Windows: Создаём MSI

Возникла тут небольшая задачка.

Есть некая программа. Разработчик этой программы периодически присылает её обновления. Эти обновления имеют хитрое расширение AAA.upg и устанавливаются с помощью специальной утилиты UUU.exe

Компьютеры, на которых используется эта программа, имеют пару особенностей. Во-первых, их много. Во-вторых, они участвуют в домене, где из соображений безопасности пользователям какие попало и откуда попало екзешники выполнять нельзя.

Получается, что остаётся два варианта установки обновлений. Первый: на каждом компьютере установить утилиту UUU.exe и настроить с ней ассоциацию файлов *.upg. Затем рассылать, скажем, по почте очередные обновления, и пусть пользователи их запускают двойным кликом. Этот способ имеет свои недостатки. Например, попытка этой утилиты с пользовательскими правами что-нибудь записать в системные каталоги будет заведомо неудачной.

Второй вариант, по-моему, гораздо более предпочтительный - воспользоваться публикацией пакетов обновлений. Однако, тут тоже есть своя сложность. Разработчик как-то не совсем адекватно относится к просьбам присылать готовые инсталляционные пакеты, пригодные для развертывания с помощью служб Active Directory. Поэтому остаётся одно - создавать нужные инсталляционные пакеты самостоятельно.

Итак, задача. Есть два файла, UUU.exe и AAA.upg. Нужно сделать инсталляционный пакет MMM.msi, который бы разархивировал эти два файла и затем выполнял команду "UUU.exe AAA.upg".

В качестве инструментов для решения этой задачи используются:
1. Архиватор 7-zip и его расширения для создания SFX-архивов (7-zip extra)
2. Конвертер исполняемых файлов в инсталляционные пакеты: http://www.exetomsi.com/freeware.php

Решение такое.

1. Создаём архив ZZZ.7z, содержащий два файла, UUU.exe и AAA.upg.

2. Из пакета 7-zip extra вытаскиваем файл 7zsd.sfx и кладём его рядом с архивом ZZZ.7z

3. Создаём файл config.txt с таким содержимым:
;!@Install@!UTF-8!
RunProgram="UUU.exe AAA.upg"
GUIMode="2"
;!@InstallEnd@!

4. Собираем самораспаковывающийся архив командой:
COPY /b 7zsd.sfx + config.txt + ZZZ.7z MMM.exe

5. Конвертируем получившийся исполняемый файл MMM.exe в MMM.msi

И, собственно, на этом всё.

Использовавшиеся источники:
http://7zsfx.info/ru/
http://paraglidernc.com/utilities/sfxsetup.htm

P.S. Важное дополнение. Оказывается, при публикации инсталляционных пакетов есть две возможности: назначить Пользовательский интерфейс при установке Простой или Полный. Простой интерфейс не позволяет создавать диалоговые окна, соответственно, если утилита UUU.exe хочет пообщаться с пользователем, процесс инсталляции вылетает с ошибкой "Не удалось назначить приложение *** из политики ***. Ошибка: в процессе установки произошла неисправимая ошибка".

Вышеуказанный конвертер генерирует пакеты, у которых этот самый Пользовательский интерфейс может быть только Простой. (Возможно, причина вот в этом: The Maximum UI option shows the UI that the author of the Windows Installer package defined.) Если требуется Полный интерфейс, то можно воспользоваться другим конвертером: http://www.exemsi.com/download.

четверг, 13 февраля 2014 г.

Почему я с недоверием отношусь к сложным конструкциям: С++

Потому что мой примитивный разум отказывается понимать вычурную логику.

Вот, например. Пишем файл main.cpp примерно такого вида:
#include <iostream>
using namespace std;

int main()
{
    int a[2];
    a[0] = 1; a[1] = 2;
    int t = 1;

    a[t] = a[--t + 1] + 1;

    cout << t << " = " << a[0] << "  " << a[1] << "\n";
}
Компилируем командой gcc main.cpp -lstdc++, запускаем. На экране выводится:
0 = 3 2
Практически тот же самый код:
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    std::vector<int> a(2);
    a[0] = 1; a[1] = 2;
    int t = 1;

    a[t] = a[--t + 1] + 1;

    cout << t << " = " << a[0] << "  " << a[1] << "\n";
}
Выводит на экран:
0 = 1 3

Разница только в объявлениях. Вот как с этим можно работать?! Как по минному полю ходить...