Ещё один способ отображения строк в Go

от автора

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

1. Нельзя использовать числа в явном виде, кроме 0.
2. Количество разрешённых математических операций тоже было ограничено.

Повторять её на Go я не стал, но решил применить один из вариантов решения, для отображения строки. Идея эта не нова, и на полноправное авторство не претендую, просто решил поделиться.

Суть в том, что строка разбивается на байты, а каждый байт преобразуется в последовательность побитовых сдвигов, и операций XOR и OR с единицей.

Выглядит это примерно так:

EAX = uint8(unsafe.Sizeof(true)) (((EAX<<EAX^EAX)<<EAX|EAX)<<EAX<<EAX<<EAX^EAX)<<EAX)

И так начнём. Модуль unsafe тут нужен лишь для функции sizeof. Если кто знает как в Go получить размер структуры другими способами, буду рад если поделитесь.

Оформляем секции Import и Const

import ( 	"fmt" 	"math/rand" 	"time" 	"unsafe" )  const ( 	EAX = uint8(unsafe.Sizeof(true)) 	ONE = "EAX" ) 

Далее нужна функция, которая будет для заданного байта, находить и генерировать такую комбинацию. Наиболее простым и очевидным вариантом было просчитать сначала шаблон, вида [0,1,1,0,1,1,…]. Где 0 — означает что число четное, 1 — число нечётное. Уменьшая каждый раз число, выполняя побитовый сдвиг вправо на 1.

Записываем это в виде кода

func getNumber(n byte) (buf string) { 	var arr []byte 	for n > EAX { 		if n%2 == EAX { 			arr = append(arr, EAX) 		} else { 			arr = append(arr, 0) 		} 		n = n >> EAX 	} } 

Таким образом длина среза arr у нас будет равна количеству шагов, которые необходимо выполнить, для получения исходного числа.

Дополним функцию getNumber

buf = ONE rand.Seed(time.Now().Unix()) for i := len(arr) - 1; i >= 0; i-- { 	buf = fmt.Sprintf("%s<<%s", buf, ONE) 	if arr[i] == EAX { 		if rand.Intn(2) == 0 { 			buf = fmt.Sprintf("(%s^%s)", buf, ONE) 		} else { 			buf = fmt.Sprintf("(%s|%s)", buf, ONE) 		} 	} } 

Пробегая по срезу arr мы генерируем строку «сдвигов», и если встречаем нечётное число, то рандомно выполняем над этим числом операцию OR или XOR с 1.

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

Ещё одна функция

func TextToCode(txt string) string { 	b := []byte(txt) 	tmp := "var str []byte\n" 	for _, item := range b { 		tmp = fmt.Sprintf("%s\nstr = append(str, %s)", tmp, getNumber(item)) 	} 	tmp += "\nfmt.Println(string(str))" 	return tmp } 

Вот собственно и всё. После запуска, для строки: «Author: GH0st3rs» получаем следующий результат:

Слабонервным не смотреть

var str []byte  str = append(str, (EAX<<EAX<<EAX<<EAX<<EAX<<EAX<<EAX^EAX)) str = append(str, ((((EAX<<EAX^EAX)<<EAX|EAX)<<EAX<<EAX^EAX)<<EAX<<EAX^EAX)) str = append(str, (((EAX<<EAX^EAX)<<EAX|EAX)<<EAX<<EAX^EAX)<<EAX<<EAX) str = append(str, ((EAX<<EAX^EAX)<<EAX<<EAX|EAX)<<EAX<<EAX<<EAX) str = append(str, (((((EAX<<EAX^EAX)<<EAX<<EAX|EAX)<<EAX^EAX)<<EAX^EAX)<<EAX|EAX)) str = append(str, (((EAX<<EAX^EAX)<<EAX|EAX)<<EAX<<EAX<<EAX^EAX)<<EAX) str = append(str, (((EAX<<EAX^EAX)<<EAX|EAX)<<EAX<<EAX^EAX)<<EAX) str = append(str, EAX<<EAX<<EAX<<EAX<<EAX<<EAX) str = append(str, EAX<<EAX<<EAX<<EAX<<EAX<<EAX<<EAX) str = append(str, (((EAX<<EAX<<EAX<<EAX<<EAX^EAX)<<EAX|EAX)<<EAX^EAX)) str = append(str, (EAX<<EAX<<EAX<<EAX^EAX)<<EAX<<EAX<<EAX) str = append(str, (EAX<<EAX^EAX)<<EAX<<EAX<<EAX<<EAX) str = append(str, ((((EAX<<EAX^EAX)<<EAX|EAX)<<EAX<<EAX<<EAX^EAX)<<EAX^EAX)) str = append(str, (((EAX<<EAX^EAX)<<EAX|EAX)<<EAX<<EAX^EAX)<<EAX<<EAX) str = append(str, (((EAX<<EAX^EAX)<<EAX<<EAX<<EAX|EAX)<<EAX^EAX)) str = append(str, (((EAX<<EAX^EAX)<<EAX|EAX)<<EAX<<EAX<<EAX^EAX)<<EAX) str = append(str, ((((EAX<<EAX^EAX)<<EAX|EAX)<<EAX<<EAX<<EAX^EAX)<<EAX^EAX)) fmt.Println(string(str)) 

» Исходный код проекта доступен на GitHub
ссылка на оригинал статьи https://habrahabr.ru/post/313486/