J0oi0

                    -- И ты ни разу не соблазнился? 
                    ни разу не поставил на руте*?.. 
                    Твердость твоя для меня удивительна.
                    ..
                    Чаплицкий поставил на первую карту 
                    пятьдесят тысяч и выиграл соника**; 
                    загнул пароли, пароли-пе***, -- отыгрался 
                    и остался еще в выигрыше...
                    ------
                      *) $ sudo -i
                     **) Sony model K.
                    ***) /etc/shadow stores a hashed version 
                       of the password. This is, for all intentsions 
                       and purposes, impossible to recover 
                       because hashing is a one way operation.
                       https://askubuntu.com/questions/383057
                       /how-to-decode-the-hash-password-in-etc-shadow

# ИСПОЛЬЗУЕМ PHP. ВВЕДЕНИЕ
~~~~~~~~~~~~~~~~~~~~~~~~~~

Компьютер взаимодействует с человеком, а контроллер с физическими процессами. И тот и другой имеют (три кита):

  1. RAM (random access memory, ОЗУ, память с произвольным доступом)
  2. I/O (input/output, ввод-вывод)
  3. CPU (central processing unit, ЦП или центральный процессор) 

Еще задолго до Восстания Машин (а в это время можно легко окунуться по старым кинолентам, книгам, музыке тех лет и воспоминаниям очевидцев) полной автономности названных девайсов (слово "устройство" побережем для связки "устройство девайса", а то "устройство устройства" как-то не нравится) добивались поэтапно:

  1. память: триггер (1918), магнитная запись на проволоку (1895), оперативное запоминающее устройство (склад Беббиджа, "store", 1834)
  
  2. I/O: -- в память надо поместить что-то из внешнего мира (ввод) и посмотреть, что там хранится (вывод).
  
  3. CPU: автоматизация ввода-вывода и обработка накопленной информации.
  

# ШАГ I. ПАМЯТЬ
~~~~~~~~~~~~~~~

На этом этапе -- сбором, обработкой* и употреблением информации пока занимается человек.

------
*) любым доступным ему способом: в уме, с карандашом и бумагой, на счетах,..
------

Для изучения вопроса будем плясать от достигнутого (Ubuntu Disco Dingo, PHP7). Достигнуто явно больше, чем понято (человечество знает больше, чем отдельно взятая личность), поэтому вот дацзибао:

  Трогай только то, что понятно.
  И вот, еще, никаких там BOM*
  
------
*) И вот тут некоторые стали позволять себе нашивать накладные карманы и опушивать рукав. Вот этого мы позволять не будем! 

   Тот самый Мюнхгаузен, 1979, 2/2 00:53:53
------
  
Начать следует между строками

  /* START HERE */
  ..
  /* EREH TRATS */
  
Пример 1. "Умная" память с ячейками для string
          (void, версия PHP 7.2 и выше).

  <?php
  
  declare(strict_types=1);

  interface smartRAMInterface {
    public function read(int $addr) : string;
    public function write(int $addr, string $value) : void;
  }

  class smartRAM implements smartRAMInterface {
    protected $RaM : array;
    
    public function read(int $addr) : string {
      return $this->RaM[ $addr] ?? "EMPTY";
    }
    
    public function write(int $addr, string $value) : void { 
      $this->RaM[ $addr] = $value;
    }
  }

  /************ START HERE ************/
  $sm = new smartRAM();

  $sm->write(3, "Hi!");
  print $sm->read(3) . PHP_EOL;
  print $sm->read(4) . PHP_EOL;

  // output:

  //   Hi!
  //   EMPTY
  
  /************ EREH TRATS ************/

  ?>
  
  
# ШАГ 2. ВВОД-ВЫВОД
~~~~~~~~~~~~~~~~~~~

Пока наша память собрана на шестеренках (склад Беббиджа) или реле (электромеханическая), читать состояние ячеек можно внешним осмотром. Не слишком удобно, но возможно. 

Наш девайс ввода-вывода будет состоять из холста в браузере и экранной клавиатуры. Нужно сделать верификацию адреса (целое число) и значения, придумать синтаксис и мнемонику команд..

Отвлечемся (не)надолго для решения похожей, но более простой задачи (Мы вернемся к smartRaM в одной из задач). 

<< 
  -------------- Полезные маски -----------------

  0 or 1 :
    '/^0|1$/'

  not negative integer : 
    '/^(0|[1-9][0-9]*)$/'

  integer :
    '/^[+-]?(0|[1-9][0-9]*)$/'

  float :
    '/^[+-]?(0|[1-9][0-9]*)\.?[0-9]*((e|E)[+-]?(0|[1-9][0-9]*))?$/'
    
  -----------Настройка "Disco Dingo" -------------

  $ sudo sed -i 's/^display_errors = Off/display_errors = On/' \
    /etc/php/7.2/apache2/php.ini

  $ sudo sed -i 's/g = E_ALL & ~E_DEPRECATED & ~E_STRICT/g = E_ALL/' \
    /etc/php/7.2/apache2/php.ini

  $ cat /etc/php/7.2/apache2/php.ini | grep '^display_err\|^err'

  error_reporting = E_ALL
  display_errors = On
  
  $ cat /etc/php/7.2/apache2/php.ini | grep 'file_uploads'
  file_uploads = On
  max_file_uploads = 20

  $ sudo systemctl restart apache2
>>

Вводим целое неотрицательное число N (натуральное или ноль). Проверяем, что ввели. Если всё вкусно, печатаем сумму 1+2+..N . 

  $ cat /var/www/html/index.php
  <!DOCTYPE html>
  <html>
    <head>
      <title>index.php</title>
      <meta charset="utf-8">
    </head>
    <body>
      <?php
        require_once('/home/virtu/exercise.php');
        
        $f = isset($_POST['submit']);
        $s = ( isset($_POST['submit']) ? $_POST['mydata'] : "");
        echo myprompt() . "<br>";
      ?>
      <form method="post" action="index.php">
          <input name="mydata" type="text" class="form-control"
              value='<?php echo "$s";?>'
              style="width: 150px; display: inline" autofocus />
          <input name="submit" type="submit" value="Run"/>
      </form>
      <?php
        if ($f) 
          exercise( $s);
      ?>
  </html>

  $ cat exercise.php
  <?php
  function myPrompt() {
    return "Enter number";
  }
  
  function verif( $aregex, $avalue) {
    $s = trim( $avalue);
    if ( 1 == preg_match( $aregex, $s)) {
      echo "You entered : " . $s . "<br/>";
      return true;
    }
    else {
      echo "No. Please repeat." . "<br/>";
      return false;
    }
  }
  
  function exercise( $as) {
  
    /************** START HERE **************/
    
    if ( verif( '/^(0|[1-9][0-9]*)$/', $as)) {
 
      $n = (int) $as;
      $ss = "";
      $summa = 0;
      for ($i = 1; $i <= $n; $i++) {
        $summa = $summa + $i;
        $ss = $ss.($i==1?"":"+").(string)$i;
      }
      echo $ss."=".(string)$summa."<br/>";
    
    }
    /************** EREH TRATS **************/

  }
  ?>
  
  
# ЗАДАЧИ С РЕШЕНИЯМИ
~~~~~~~~~~~~~~~~~~~~
 
index.php  не трогаем, задачу решаем в exercise.php, с работающего примера делаем копию, например так:

  $ cp exercise.php 01.php

------------------------------------------------------------------------

01. Ввести фразу, показать слова в столбик. Например:

  каждый  охотник   желает знать   где     сидит фазан
  красный оранжевый желтый зеленый голубой синий фиолетовый
  
Решение:

  /************** START HERE **************/
  
  if ( verif( '/^.+$/', $as)) {
    $a = explode(" ", $as);
    foreach ($a as $v) if (trim($v)) echo $v."<br>";
  }
  
  /************** EREH TRATS **************/

------------------------------------------------------------------------

02. Ввести слово, показать буквы в столбик. 

Решение

  $as = trim( $as);
  if ( verif( '/^.+$/', $as)) {
    $a = preg_split('//u', $as, NULL, PREG_SPLIT_NO_EMPTY);
    for ($i = 0; $i < sizeof( $a); $i++) 
      // [] hates unicode characters
      echo $a[$i]."<br>";
  }

Это решение есть здесь:

  https://shra.ru/2017/01/razbit-slovo-na-bukvy-v-php/
  
Замечание: Для юникода не все так прозрачно, как для ascii-7. Гугль в помощь!

------------------------------------------------------------------------

03. Сложить два целых числа.

  $as = trim($as);
  if (verif('/^[+-]?(0|[1-9][0-9]*)[\s]+[+-]?(0|[1-9][0-9]*)$/',as)) {
    $a = preg_split('/[\s]+/', $as);
    echo $a[0]."+".$a[1]."=".(string)(0+$a[0]+$a[1]);
  }

Замечание: Если "заткнуть" верификатор, то все намного проще:

  $a = explode(" ", $as); echo $a[0]+$a[1];

------------------------------------------------------------------------

04. МНОГО ДАННЫХ: Загрузить фото.

В корневую папку web сервера (/var/www/html/) загрузить два скрипта:

up.php*

  <!DOCTYPE html>
  <html>
  <head>
      <title>up.php</title>
      <meta charset="utf-8">
  </head>
  <body>

  <form action="upload.php" method="post" enctype="multipart/form-data">
      Выберите файл для загрузки:
      <input type="file" name="fileToUpload" id="fileToUpload">
      <input type="submit" value="Загрузить" name="submit">
  </form>

  </body>
  </html>

------
*) https://www.w3schools.com/php/php_file_upload.asp
------

upload.php

  <!DOCTYPE html>
  <html>
  <head>
      <title>up.php</title>
      <meta charset="utf-8">
  </head>
  <body style="background-color: lightblue;">

  <?php
  $target_dir = "uploads/";
  $target_file = $target_dir.basename($_FILES["fileToUpload"]["name"]);
  if(isset($_POST["submit"])) {
    if (move_uploaded_file( 
            $_FILES["fileToUpload"]["tmp_name"], 
            $target_file)) {
      echo "Файл " . 
           basename( $_FILES["fileToUpload"]["name"]) . 
           " загружен.";
      echo "Имя файла :".$_FILES['fileToUpload']['name']."<br/>";
      echo "Размер    :".$_FILES['fileToUpload']['size']."<br/>";
      echo "Тип файла :".$_FILES['fileToUpload']['type']."<br/>";

      echo "<img src=\"$target_file\" width=\"222\" height=\"323\">";

    } else {
      echo "Произошла ошибка при загрузке файла.";
    }
  }
  ?>
  </body>
  </html>

------------------------------------------------------------------------

05. Ввод-вывод в двоичном коде

  $ echo '<?php echo decbin( bindec('11') + bindec('111')); ?>' | php
  1010
  
------------------------------------------------------------------------

06. Какую кнопку нажали?

  <!DOCTYPE html>
  <html>
  <head>
      <title>button.php</title>
      <meta charset="utf-8">
  </head>
  <body>
  <?php
  if (isset($_POST['eins'])) echo $_POST['eins'];
  else if (isset($_POST['zwei'])) echo $_POST['zwei'];
  else if (isset($_POST['drei'])) echo $_POST['drei'];
  else echo "Ни разу";
  ?>
  <form action="" method="post">
      <input type="submit" value="Раз" name="eins">
      <input type="submit" value="Два" name="zwei">
      <input type="submit" value="Три" name="drei">
  </form>
  </body>

------------------------------------------------------------------------

07. Показать координаты щелчка мышкой по изображению:

идея:
  
  https://www.plus2net.com/php_tutorial/php_image_coordinates.php

mouse.php

  <?php
  echo isset($_POST['mouse_x']) &&  isset($_POST['mouse_y']) ?
     "X=".$_POST['mouse_x'].", Y=".$_POST['mouse_y'] :
     "X неизвестен, Y неизвестен";
  ?>
  <form action="" method=post>
    <input type="image"
           alt= "Показать координаты щелчка мышкой по изображению"
           src= "uploads/xy.png"
           name="mouse"
           style=cursor:crosshair;
    />
  </form>

------------------------------------------------------------------------


# 26.12.2018 ЗАДАЧИ БЕЗ РЕШЕНИЙ
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# Школа. Арифметика. Операции
  
  1. Ввести два целых числа, каждое из которых в диапазоне 0..999. Показать результат деления нацело и остаток от деления. 
  
     Пример: 8 / 3 = 2 ; 2
  
  2. Ввести число x. Результат вычислить по формуле: x в степени 3.4
  
  3. Ввести от одного до пяти целых чисел. Показать наибольшее.
  
  4. Ввести целое число от 0 до 100. Показать словами.
  
     ноль один два три четыре пять шесть семь восемь девять
     десять одиннадцать двенадцать тринадцать четырнадцать
     пятнадцать шестнадцать семнадцать восемнадцать девятнадцать
     двадцать тридцать сорок пятьдесят шестьдесят семьдесят
     восемьдесят девяносто сто. floor($a/$b) или (int)($a/$b)
     
  5. Ввести целое число от 0 до 10. Посчитать факториал.
  
     sudo apt install php-bcmath
     sudo systemctl restart apache2
     
  6. Ввести и выполнить команду для перевода температуры между шкалой Цельсия и Фаренгейта:
  
     цф <число>
     фц <число>
     фф <число>
     цц <число>
     
     1) Ниже -273.15 по Цельсию не бывает
     2) Формула перевода (K&R): celsius = (5.0/9.0) * (fahr-32.0);

  7. Разделить банан весом в сто грамм на равные части по два килограмма каждая.
  
  (Нужно разделить на 0.05 равных частей)


# Другие системы счисления.
  
Перевод числа в диапазоне 1..3999
     
   1.  10 -> 2   взвешиваем на весах с гирьками весом
                 1,2,4,8,16,32,64,128,256,512,1024,2048
                 
   2.  10 -> 8   сначала переводим в двоичную систему,
                 потом по три цифры справа, пустые позиции это 0.
                 
   3.  10 -> 16  сначала переводим в двоичную систему,
                 потом по четыре цифры справа, пустые позиции это 0.
                 
   4.  2  -> 8   по три цифры справа, пустые позиции это 0.
   
   5.  2  -> 10  по формуле 2**n * a[n] + .. 2**0 * a[0] 
   
   6.  2  -> 16  по четыре цифры справа, пустые позиции это 0.
   
   7.  8  -> 2   каждую цифру заменяем тройкой нулей и единиц
   
   8.  8  -> 10  по формуле 8**n * a[n] + .. 8**0 * a[0] 
   
   9.  8  -> 16  каждую цифру заменяем четверкой нулей и единиц
   
  10. 16  -> 2   каждую цифру заменяем четверкой нулей и единиц

  11. 16  -> 8   через двоичную: 16 -> 2 -> 8
  
  12. 16  -> 10  по формуле 16**n * a[n] + .. 16**0 * a[0]
  
  13. 10  -> Roman  1..3999  I..MMMCMXCIX 
  
  14. Roman -> 10   1..3999  MDCLXVI (1666)
  
------
Замечания

  операция ** означает "в степени" (fortran..)

  триады:  0:000  1:001  2:010  3:011  4:100  5:101  6:110  7:111

  тетрады: 0:0000 1:0001 2:0010 3:0011 4:0100 5:0101 6:0110 7:0111
           8:1000 9:1001 A:1010 B:1011 C:1100 D:1101 E:1110 F:1111

  Roman:   I=1  V=5  X=10  L=50  C=100  D=500  M=1000
            https://www.romannumerals.org/converter

------


# Операции в двоичном коде:

   1.  -   унарный минус           -00101101 =           11010011
   2.  +   сложение                 11 +  111 =  +1010 = 00001010
   3.  -   вычитание                11 -  111 =  -100  = 10000000
   4.  *   умножение                11 *  111 = +10101 = 00010101
   5.  /   деление                  111 /  11 = +10; +1
   6.  %   остаток                  111 %  11 = 1
   6.  &&  логическое AND           101 && 10 = false
   7.  ||  логическое OR            101 || 10 = true
   8.  !   логическое NOT          !101       = false
   9.  &   побитовое   AND          101 &  10 = 000
  10.  |   побитовое   OR           101 |  10 = 111
  11.  ^   побитовое   XOR          111 ^  10 = 001
  12.  ~   побитовое   NOT         ~101       = 010
  13.  <<  побитовый сдвиг влево    101 << 10 = 10100
  14.  >>  побитовый сдвиг вправо   101 >> 10 = 1
  15.  ?:  если ? то : иначе        110 ? 111 : 10 = 111
  16.  ??  NULL ?? 'default';       NULL ?? "!!!"  = "!!!"
  17.  >   больше чем               101 >  10 = true
  18.  >=  больше или равно         10  >= 10 = true
  19.  <   меньше чем               101 <  11 = false
  20.  <=  меньше или равно         10  <= 11 = true
  21.  !=  не равно                 10  != 11 = true
  22.  ==  равно ли?                10  == 11 = false
   
# Геометрия


# Упростить выражение


# ОС. Регулярные выражения (Henry Spenser regex)
  
  ^ $ ( ) [] {} . * + ? | \
       
Настроить задачу "если всё вкусно" так: Ввести текст. Если ввод считается допустимым то печатать введенный текст, иначе редактировать ввод.
   
   1. Запретить пробелы в начале
   
   2. Запретить пробелы в конце
   
   3. Только 0..7
   
   4. Только Катя Света Таня
   
   5. Если в тексте встречаются слова "слон" "злой" печатать "OK", иначе редактировать ввод.
   
   6. Если в тексте буква "е" (кириллица) встречается именно три раза подряд (жираф -- длинношеее животное) печатать "OK".
   
   7. Введенный текст длиной ровно пять любых символов.
   
   8. * ноль или больше раз
   
   9. + один или больше раз
   
  10. ? в смысле ноль или один раз
  
  11. ? в смысле жадные и ленивые квантификаторы
      https://myrusakov.ru/php-regexp-greedy.html
      
  12. \ червоточина
  
   
# Поиск и редактирование текста.

  1. ed -- скриптом (подменой стандартного ввода) 
     https://www.ibm.com/developerworks/community/blogs/brian
           /entry/ed_editor?lang=en

  2. sed - скриптом


# API (PHP)


# Фильтры

  Было. См. http://nelus.tpt.edu.ee "Фильтры"


# Мониторинг

  Будет в курсе по Linux/BSD


# Ссылки

  1. https://github.com/hayeah/playing-cards-assets
  
  2. No Joker's

       https://upload.wikimedia.org/wikipedia
         /commons/5/55/Atlasnye_playing_cards_deck.svg
    
  3. Google images: play cards png joker
    

# 26.12.2018 DISCO SO FAR
~~~~~~~~~~~~~~~~~~~~~~~~~

  # apt-get update
  # apt-get upgrade
  # apt-get install openssh-server ncurses-dev tasksel
  # tasksel install lamp-server
  # apt-get autoremove
  # apt-get clean
  # cat /etc/default/grub | grep "quiet"
  GRUB_CMDLINE_LINUX_DEFAULT="" # "quiet splash"
  # update-grub
  # dd if=/dev/zero of=biig; rm biig

  Software Updater -> Settings -> Updates
    Automatically check for updates: Never
  Devices -> Insert Guest Additions CD Image:
    Install Guest Additions
  VirtualBox Manager
    if NAT
      network -> Advanced -> Port Fowarding:
      
        127.0.0.1:22 to 10.0.2.15:2222
        127.0.0.1:80 to 10.0.2.15:8080

Fix: J0QDU

  1. Added estonian, russian keyboard layouts to
      Settings -> Region and Language -> Input Sources
      
  2. $ touch ~/.Xauthority

Ссылки:
       
  1. https://www.linode.com/docs/web-servers/lamp
       /install-lamp-stack-on-ubuntu-18-04/
       
  2. https://linuxconfig.org
       /how-to-install-java-on-ubuntu-18-04-bionic-beaver-linux


26.12.2018. Учимся
-------------------

Сказано Вначале было Слово. Верно. Есть информация в некоторой адресуемой "smart" памяти. "Smart" потому, что есть API (application program interface) на две команды: 

  $err   = writeSM( $address, $value);
  $value = readSM( $address);
  
Напишем эти функции на PHP седьмой версии (нужны интерфейсы, классы, строгая типизация и скалярные типы):

<<
gettype():  Possible values for the returned string are:

  o  "boolean"       o  "object"
  o  "integer"       o  "resource"
  o  "double" *1     o  "resource (closed)" *2
  o  "string"        o  "NULL"
  o  "array"         o  "unknown type"        
  
------  
*1) for historical reasons "double" is returned in case of a float, and not simply "float")
*2) as of PHP 7.2.0
------
>>

Для начала, никаких там UTF-x with BOM, иначе:

  Fatal error: strict_types declaration must be the very first statement in the script in ..
  
Перегрузка (overloading) пока не работает, читаем здесь:

  https://bugs.php.net/bug.php?id=69961
  
Вообще говоря, введение в php строгой типизации тянет за собой целую бороду из ожиданий: сигнатуры методов, шаблоны (template), прототипы..

Пример 1.

  <?php
  // Strict mode
  declare(strict_types=1);
  function sum(int ...$ints) {
    return array_sum($ints);
  }
  print(sum(2, 3, 4));
  ?>

Пример 2.

  <?php
  declare(strict_types=1);
  class Seven {
    public function dup(int $ix) : int {
      return $ix;
    }
  }
  $S = new Seven();
  print($S->dup(5));
  ?>


# 25.12.2018. ПРО UTF-8
-----------------------

I. "UTF-8: КОДИРОВАНИЕ И ДЕКОДИРОВАНИЕ"*

------
*) https://habr.com/post/138173/
------

Вот выдержки из статьи (от слова выдергивать):

А. Правильно:

Когда-то я думал что есть Юникод, а есть UTF-8. Позже я узнал, что ошибался. UTF-8 является лишь представлением Юникода в 8-битном виде.

Б. Вступает в противоречие сам с собой:

Да: Символы же с кодами от 128 кодируются 2-мя байтами, с кодами от 2048 -- 3-мя, от 65536 -- 4-мя. Так можно было бы и до 6-ти байт дойти, но кодировать ими уже ничего. 

  0x00000000 -- 0x0000007F: 0xxxxxxx
  0x00000080 -- 0x000007FF: 110xxxxx 10xxxxxx
  0x00000800 -- 0x0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
  0x00010000 -- 0x001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
  ..

Но позже: Похожим образом можем продолжить и для больших кодов, но если символ за пределами U+FFFF придется иметь дело с UTF-16 суррогатами.

В. Собственно, интересует только кириллицу добавить.

Если код символа меньше 2048, то берем последние 6 бит и первые 5 бит кода символа. К первым 5 битам добавляем 0xC0 и получаем первый байт последовательности, а к последним 6 битам добавляем 0x80 и получаем второй байт.

II. Появляются вопросы: 

  1. Что такое БОМ?

BOM: The byte order mark (BOM) is a Unicode character, U+FEFF.. The UTF-8 representation of the BOM is the (hexadecimal) byte sequence 0xEF,0xBB,0xBF*. 
------
*) https://en.wikipedia.org/wiki/Byte_order_mark
------
        это третий байт (потому что 111, самый левый)
        |         есть байт слева
        |         |       |
        1110     10       10
  FEFF:     1111   111011   111111
        --------------------------
        11101111 10111011 10111111
        E   F    B   B    B   F
        
  2. Коды кириллицы?
  
  Ё U+0401  А..Я U+0410..U+042F
  ё U+0451  а..я U+0430..U+044F
  
        это второй байт, (потому что 11, самый левый)
        |         есть байт слева
        |         |
        110      10
  0451:    10001   010001
        -----------------
        11010001 10010001
        D   1    9   1
 
        110      10
  0410:    10000   010000
        -----------------
        11010000 10010000
        D   0    9   0

  3. Каким символам соответствуют коды с 11000000 по 11111111?
  
  00xxxxxx --  0.. 63
  01xxxxxx -- 64..127
  10xxxxxx -- UTF-8, есть байт слева
  11xxxxxx -- illegal

Your proposed encoding is similar to the original FSS/UTF proposal*. Ken Thompson and Rob Pike wanted the self-synchronizing property.

  U+0000     U+007F    1     0xxxxxxx
  U+0080     U+3FFF    2     10xxxxxx  xxxxxxxx
  U+0800     U+1FFFFF  3     110xxxxx  xxxxxxxx  xxxxxxxx

------
*) https://softwareengineering.stackexchange.com/questions/262227
     /why-does-utf-8-waste-several-bits-in-its-encoding
     
   cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt 
------


# 24.12.2018. ОБО ВСЕМ ПОНЕМНОГУ
--------------------------------

Данные надо где-то хранить. Если отбросить наскальные рисунки сохраняющиеся на стенах пещер, манускрипты на папирусе и бумажные книги, то рано или поздно мы придем к идее хранения на бесконечной цепочке, где каждое звено может хранить только определенное количество символов. Так, ячейки (звенья) способные хранить ' ', '0', '1' образуют ленту Тьюринга. 

Ячейки для хранения '0' или '1' легко создать, например, на основе триггеров. Для быстрого доступа каждая ячейка может иметь свой адрес. Часто используют адреса многоуровневые, например так:

  байт.бит

Рис 1.1  Байтовая лента byTa (byte Tape).

      +---+---+---+    +---+---+   
  MSB |   |   |   |    |   |   |
      +---+---+---+    +---+---+   
    6 |   |   |   |    |   |   |
      +---+---+---+    +---+---+   
    5 |   |   |   |    |   |   |
      +---+---+---+    +---+---+   
    4 |   |   | 1 |    |   |   |
      +---+---+---+    +---+---+   
    3 |   |   |   |    |   |   |
      +---+---+---+    +---+---+   
    2 |   |   |   |    |   |   |
      +---+---+---+    +---+---+   
    1 |   |   |   |    |   |   |
      +---+---+---+    +---+---+   
  LSB |   | 0 |   |    |   |   |
      +---+---+---+    +---+---+   
        0   1   2   ..  n-1  n   ..
        
На рисунке в ячейку с адресом 1.0 записан '0' , а в ячейку 2.4 '1'

  #include <stdio.h>

  #define N  22
  #define B  8
  /*                       01234567890123456789012 */
  unsigned char byTa[N] = "GOODBYE C, HELLO PHP!\0";

  void writeTo( unsigned char* byTa, int x, int b, int v) {
    byTa[ x] = v ? byTa[x] | (1 << b) : byTa[x] & ~(1 << b);
    return;
  }

  int readFrom( unsigned char* byTa, int x, int b) {
    return ( byTa[x] & (1 << b)) ? 1 : 0;
  }

  void map( unsigned char* byTa) {
    int i, j;
    
    for (i=0; i<N; i++)
      fputs("+---", stdout); 
    fputs("+\n", stdout);
    
    for (j=B-1; j>=0; j--) {
      for (i=0; i<N; i++)
        printf("| %c ", '0'+readFrom( byTa, i, j)); 
      fputs("|\n", stdout);
    }
    
    for (i=0; i<N; i++)
      fputs("+---", stdout); 
    fputs("+\n", stdout);
    
    return;
  }

  int main() {
    map( byTa);

    writeTo( byTa, 1, 4, 1);
    writeTo( byTa, 1, 5, 1);
    map( byTa);
    writeTo( byTa, 1, 4, 0);
    map( byTa);

    return 0;
  }

OK, это был C для проверки идеи, а теперь PHP.

  <?php
  $byTa = str_split("GOODBYE C, HELLO PHP!\0");

  function writeTo(&$byTa, $x, $b, $v) {
    $byTa[$x] = 
      $v == 1 ?
      chr( ord($byTa[$x]) | (1 << $b)) : 
      chr( ord($byTa[$x]) & ~(1 << $b));
  }

  function mapbt($byTa) {
    echo " ";
    for($i=0; $i<sizeof($byTa); $i++)
      echo "+---";
    echo "+" . PHP_EOL;

    for($j=0; $j<8; $j++) {
      for($i=0; $i<sizeof($byTa); $i++) {
        $v = str_pad(decbin(ord($byTa[$i])), 8, "0", STR_PAD_LEFT)[$j];
        echo " | " . $v;
      }
      echo " |" . PHP_EOL;
    }

    echo " ";
    for($i=0; $i<sizeof($byTa); $i++)
      echo "+---";
    echo "+" . PHP_EOL;
  }
  
  mapbt($byTa);
  writeTo($byTa,0,7,1);
  mapbt($byTa);
  ?>

------------------------------------------------------------------------

## ПРИЛОЖЕНИЕ А. 

? Для чего переводишь и добавляешь в свои заметки ?

  1. Тестирую качество автоперевода (тренды улучшение, деградация, коммерциализация/монетизация)

  2. Дополнительное время, уделенное проработке статьи, позволяет лучше усвоить прочтенное.

  3. GPLiZe!..


# SCRIPT FILE EDITS WITH THE "ED" EDITOR
# РЕДАКТИРОВАНИЕ ФАЙЛА СКРИПТА С ПОМОЩЬЮ РЕДАКТОРА "ED"

brian_s
Aug 20 2012

  https://www.ibm.com/developerworks/community/blogs
    /brian/entry/ed_editor?lang=en

The "ed" editor has for the most part been forgotten as a piece of UNIX history.   But it can still be very handy when scripting file edits, especially when the script must work across multiple UNIX variants.
~ 
Редактор "ed" большей частью оказался забыт, как фрагмент истории UNIX. Но он все еще может быть очень удобен при редактировании файлов сценариев, особенно когда сценарий должен работать в нескольких вариантах UNIX.
 
ed is a "line editor".   What this basically means is it is designed to work on a teletype (aka keyboard with a printer).   This makes it challenging to use as an interactive editor, but it is perfect for scripting.  ed is part of the Single UNIX Specification so it should exist on any system claiming to be UNIX, so it is a good utility to rely on in your scripts if they are cross platform.
~ 
ed - это "редактор строк". Это означает, что он был задуман для работы с телетайпом (клавиатура с принтером). Это затрудняет его использование как интерактивного редактора, но идеально подходит для написания сценариев. ed является частью Единой спецификации UNIX, поэтому он должен быть в любой системе, претендующей называться UNIX, так-как это хорошая утилита которую стоит положиться, если Ваши скрипты кроссплатформенные.
 
Many systems such as Linux support the "sed" command with the "-i" flag that specifies the file should be edited in place.   Unfortunately systems such as AIX don't support an inline edit mode with sed so you either have to create temporary files (ugly in my opinion) or use something different such as ed. 
~
Многие системы такие как Linux поддерживают команду "sed" с флагом "-i", который указывает, что файл должен редактироваться на месте. К сожалению, такие системы, как AIX, не поддерживают режим редактирования на месте с помощью sed, поэтому вам придется либо создавать временные файлы (на мой взгляд, безобразно), либо использовать что-то другое, как, например, ed.

All ed commands specify a range of lines (or a "," for the entire file), and then a command.   For example, within ed you can display lines 1 through 5 with the command "1,5l", or you can display the entire file with ",l".  
~
Все команды ed задают диапазон строк (или "," для всего файла), а затем команду. Например, вы можете отобразить строки с 1 по 5 с помощью команды "1.5l", или вы можете отобразить весь файл с помощью ", l".

Here are some example command lines to edit files that can be used from scripts. 
~
Вот несколько примеров команд для редактирования файлов, которые можно использовать из скриптов.

First off, we will edit the "sshd_config" file and replace the line "#Port 22" with "Port 222".   To do this we use printf to pipe the commands we want to run to ed.   In between each ed command we put a "\n" to put a carriage return / new line. 
~
Прежде всего, мы будем редактировать файл "sshd_config" и заменять строку "#Port 22" на "Port 222". Чтобы сделать это мы используем printf для передачи по трубе команд, которые мы хотим выполнить. В каждой команде ed мы ставим "\n", чтобы вставить перевод каретки / новую строку.

  $ cat sshd_config | grep "Port "                         
  #Port 22
  $ printf ",s/^#Port 22$/Port 222\nw\nq\n" | ed sshd_config
  3237
  Port 222
  3237
  $ cat sshd_config | grep "Port "                         
  Port 222

So in this example we are telling ed to first run ",s/^#Port 22$/Port222".   The first comma means apply to all lines, the "s" means search, the "^#Port 22$" means to look for a line that begins (^) and ends ($) with "Port 22".   The "/" means replace, and the "Port 222" is what we want it to be replaced with.   The "w" means write the file.  The "q" means quit.  
~
Итак, в этом примере мы говорим, чтобы ed сначала запустил ",s/^#Port 22$/Port222". Запятая вначале означает искать строку с текстом "#Port 22", которая не содержит никакого другого текста (начинается перед # (^) и заканчивается после 22($)). "/" Означает "заменить", а "Port 222" -- это то, чем мы хотим заменить. "w" означает запись файла. "q" означает выход.

Here is an example of adding a line to a file.   For example, lets say we want to add the comment line "Updated port to 222 on 8/19/12" to the top of the sshd_config file:
~
Вот пример добавления строки в файл. Например, мы хотим добавить строку комментария "Updated port to 222 on 8/19/12" в начало файла sshd_config: 

  $ printf "1\ni\n#Updated port to 222 on 8/19/12\n.\n\nw\nq\n" | \
    ed sshd_config
  3237
  $ head -n 1 sshd_config
  #Updated port to 222 on 8/19/12
 
The "1" means to go to line 1, the "i" means insert mode, the "#Updated port to 222 on 8/19/12" is the text we are adding, the "." on the line by itself means to go back to command mode, the "w" is write, and the "q" is quit.  
~
Запись "1" означает перейти к строке 1, "i" означает режим вставки, "#Updated port to 222 on 8/19/12" -- это текст, который мы добавляем, "." в новой строке означает вернуться в командный режим, «w» - запись, а «q» - выход.

You can also easily delete lines.  Lets suppose for example we decide to delete the "Port 222" line from the file:
~
Вы можете также легко удалить строки. Предположим, например, что мы решили удалить строку «Порт 222» из файла:

  $ cat sshd_config | grep ^Port
  Port 222
  $ printf ",g/^Port 222$/d\nw\nq\n" | ed sshd_config
  3269
  3260
  $ cat sshd_config | grep ^Port                   
 
As you can see ed is a powerful utility to edit files from scripts quickly and easily. 
~
Как видите, ed это мощная утилита для быстрого и простого редактирования файлов.
  