← All posts tagged code

Kim

Вот @alv в #2677608 заявляет, что мол aisleriot карты не тасует. Давайте пойдём в исходники (исходник взят из https://github.com/GNOME/aisleriot.git) и проверим. В aisleriot/games/freecell.scm прямо сказано

(define (new-game)
  (initialize-playing-area)
  (set-ace-low)
  (make-standard-deck)
  (shuffle-deck)
...
  (deal-initial-setup)
...)

Вот оно создаёт калоду, тасует её и 

(define (deal-initial-setup)
  (let ((fields (list field-1 field-2 field-3 field-4
                               field-5 field-6 field-7 field-8))
        (half-fields (list field-1 field-2 field-3 field-4)))
    (deal-cards-face-up-from-deck DECK
                                  (append fields fields fields
                                          fields fields fields
                                          half-fields))))

раздаёт по очереди шесть раз на восемь полей, а потом ещё один раз на первые четыре.

Может тусует криво? Смотрим в aisleriot/games/api.scm:

(define-public (shuffle-deck)
  (let* ((vec (list->vector DECK))
         (len (vector-length vec)))
    (set! DECK (shuffle-deck-helper vec '() 0 len))))
(define-public (shuffle-deck-helper deck result ref1 len)
  (if (zero? len)
      result
      (let* ((ref2 (+ ref1 (aisleriot-random len)))
             (val-at-ref2 (vector-ref deck ref2)))
        (vector-set! deck ref2 (vector-ref deck ref1))
        (shuffle-deck-helper deck (cons val-at-ref2 result) (+ ref1 1) (- len 1)))))

Что тут происходит? Мы рендомно выбираем элемент из списка начиная с (количество уже выбранных) до (количество карт в колоде). Запоминаем выбранный элемент, а на его место в колоду кладём элемент с минимальным не выбранным номером. Например при выборе самой первой карты aisleriot-random вернул нам номер 27, тогда мы берём 27 карту, откладываем её в отдельную стопку, а на её место кладём первую карту. В следующий раз мы выбираем из разложенных карт начиная со _второй_. 

Ну может всё таки брешут схемокодеры и косяк в aisleriot-random? Проверяем метод в aisleriot/games/card-monkey.scm:

(define-public (aisleriot-random n)
    (random n))

Действительно, тут сложно возражать. Так что либо в версии guile у @alv random совсем не random, либо что-то брешит этот ваш @alv. На всякий случай проверим и исходник guile (исходник получен по apt-get source guile-2.0). Не углубляясь в реализацию можем увидеть следующее guile-2.0-2.0.9+1/libguile/random.c:

/*
 * The prepackaged RNG
 *
 * This is the MWC (Multiply With Carry) random number generator
 * described by George Marsaglia at the Department of Statistics and
 * Supercomputer Computations Research Institute, The Florida State
 * University (http://stat.fsu.edu/~geo).
 *
 * It uses 64 bits, has a period of 4578426017172946943 (4.6e18), and
 * passes all tests in the DIEHARD test suite
 * (http://stat.fsu.edu/~geo/diehard.html)
 */

Так вот, период 4578426017172946943 немного больше, чем 12, так что брешит этот ваш @alv.

Kim

В общем не осилил перевести эту железяку в low power run mode. Фигачу такой код:

#include <libopencm3/stm32/rcc.h> 
#include <libopencm3/stm32/pwr.h> 
#include <libopencm3/stm32/flash.h> 

int main()
{
  clock_scale_t myclock_config = {
    .hpre = RCC_CFGR_HPRE_SYSCLK_DIV2,
    .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
    .ppre2 = RCC_CFGR_PPRE2_HCLK_NODIV,
    .voltage_scale = RANGE2, // Документация требует Range2 для low power run mode
    .flash_config = FLASH_ACR_LATENCY_0WS,
    .apb1_frequency = 65536,
    .apb2_frequency = 65536,
    .msi_range = RCC_ICSCR_MSIRANGE_65KHZ, // Для работы требуется MSIRANGE не больше первого. Ставим нулевой.
  };
  rcc_clock_setup_msi(&myclock_config);
  rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_PWREN);
  PWR_CR |= PWR_CR_LPSDSR;
  PWR_CR |= PWR_CR_LPRUN;
  while(1) {
      __asm__("nop");
    }
}

А в результате, хоть делай "PWR_CR |= PWR_CR_LPRUN;" хоть не делай -- жрёт оно под 1 милиампер, вместо ожидаемых 40 микроампер.

Kim

Всё сломалось? Рутрекер редиректит на какую-то унылую <https://sites.google.com/site/sicestaeternus/>. Пруф:

$ telnet rutracker.org 80
Trying 72.8.150.30...
Connected to rutracker.org.
Escape character is '^]'.
GET / HTTP/1.1
host: rutracker.org

HTTP/1.1 301 Moved Permanently
Date: Tue, 14 Aug 2012 03:45:50 GMT
Server: Apache/1.3.42 (Unix) PHP/5.3.8 with Suhosin-Patch
X-Powered-By: PHP/5.3.8
Cache-Control: public, max-age=15
X-Abuse: URL redirection provided by freedns.afraid.org - please report any misuse of this service
Location: https://sites.google.com/site/sicestaeternus/
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html

0

Connection closed by foreign host.
$

Kim

В перле можно вызывать функции следующим способом:
> $ perl -e 'sub xx {print "Hello\n"}; ("xx")->(1)'
> Hello

Соответственно если внутри скобок есть какой-то вызов, то он отработает и вызов нового метода будет от результата:
> $ perl -e 'sub ss { return "xx" }; sub xx {print "Hello\n"}; (ss)->(123);'
> Hello

Тут всё прекрасно, но есть забавное поведение в случае возврата булевого значение из встроенной функции. Если возвращается false, то всё нормально:
> $ perl -e '(exists $h{1})->()'
> Undefined subroutine &main:: called at -e line 1.

А если возвращается true, то мы получаем особую перловую магию:
> $ perl -e '++$h{1}; (exists $h{1})->()'
> $

Причём возврат булевого значения из определённых пользователем методов так не работает:
> $ perl -e 'sub x {1==1}; (x)->()'
> Undefined subroutine &main::1 called at -e line 1.
> $ perl -e 'sub x {return 1==1}; (x)->()'
> Undefined subroutine &main::1 called at -e line 1.

Зато булево значение можно передавать внутрь:
> $ perl -e 'sub x {$_[0]->(1)}; x(1==1);'
> $ perl -e 'sub x {shift->(1)}; x(1==1);'
> $ perl -e 'sub x {my $x=shift; $x->(1)}; x(1==1);'
> Undefined subroutine &main::1 called at -e line 1.
> $

В чём тут магия спросите вы? А магия тут в том как перл хранит переменные и вызывает методы. Если вдруг так случилось, что в вашей скалярной (SV в терминах перловых исходников) переменной оказалась не строка "", не число 1, а волшебная переменная из кода на C под именем PL_sv_yes, которая в исходниках перла описана в pod/perlapi.pod, то при вызове метода (а это действие реализовано в методе PP(pp_entersub) в файле pp_hot.c) вы попадёте на код pp_hot.c:2856:
> if (sv == &PL_sv_yes) {		/* unfound import, ignore */
> …
>   RETURN;
> }

Таким образом знайте, что вызов метода, где в качестве ссылки на метод используется значение true, интерпретируется как импорт несуществующего модуля и игнорируется. Сраные костыли, да.

Kim

Взять X параграфов текста, размер которых ещё влезает в четыре килобайта. 

(defun byte-count-in-region (start end)
  (string-to-number
   (with-output-to-string (call-process-region start end
					       "wc" nil standard-output nil
					       "-c"))))
(defun select-juickable-paragraph-set ()
  (interactive)
  (let ((start (point))
	(block-length 4096))
    (while (and (< (byte-count-in-region start (point)) block-length)
		(< (point) (point-max)))
      (forward-paragraph))
    (if (> (byte-count-in-region start (point)) block-length) 
	(backward-paragraph))
    (if (<= (point) start)
	(goto-char start))
    (set-mark start)
    (message "Current region size is small enough for juick")))

Как можно сделать это короче в два раза? И почему в емаксе до сих пор нет какого-нибудь forward-byte?

Kim

#include <stdio.h>
#pragma pack(push,1)
struct __attribute__ ((ms_struct)) p1 /* без атрибута в MSVC -- 13 */
{
  char c;
  int  i;
};
#pragma pack(pop)
struct __attribute__ ((packed, ms_struct)) p2
{
  char c;
  int  i;
};
struct __attribute__ ((packed, gcc_struct)) p3
{
  char c;
  int  i;
};
int main (void)
{
  printf ("p1: %d\np2: %d\np3: %d\n", sizeof (struct p1), sizeof (struct p2),
	  sizeof (struct p3));	/* Ответ: 5 8 5 */
}

Я правильно понимаю, что отсутствие упаковки в случае p2 это бага GCC (gcc version 4.6.2)? То есть по идее два определения:
> #pragma pack(push,1)
> struct __attribute__ ((ms_struct)) p1 { ... };
> #pragma pack(pop)
и
> struct __attribute__ ((ms_struct, packed)) p2 { ... };
должны быть эквивалентны.

Кому интересно, отличия в запаковке между MSVC и GCC можно увидеть на таком примере:

#include <stdio.h>
#pragma pack(push,1)
struct __attribute__ ((ms_struct)) ms /* Соответствует поведению MSVC */
{
  unsigned long bf_1 : 12;
  unsigned long bf_2 : 12;
};
struct __attribute__ ((gcc_struct)) gcc
{
  unsigned long bf_1 : 12;
  unsigned long bf_2 : 12;
};
#pragma pack(pop)
int
main (void)
{
  printf ("ms: %d\n" "gcc: %d\n", /* Ответ: 4 3 */
	  sizeof (struct ms), sizeof (struct gcc));
}