challenge バイナリクロック

 時刻を二進数相当の表現で出力する時計アプリケーションを書いてください。
 20:18の場合,例えば以下の様な出力をするイメージです。

出力例:
 ■□■□□
□■□□■□
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#! c:\ruby\bin\ruby.exe -Ks

String.class_eval do |string|
    def words
        self.split(//)
    end
    def fix_width(width, padding)
        (self.words.size > width) ? self : (padding * (width - self.words.size) + self)
    end
end

Fixnum.class_eval do |fixnum|
    alias :to_s_orig :to_s
    def to_s(base, width)
        binary = self.to_s_orig(base).fix_width(width, "0")
    end
end

class BinaryClock
    attr_accessor :now
    def initialize
        self.now = Time.now
    end
    def print
        output(self.now.hour.to_s(2, 5))
        output(self.now.min.to_s(2, 6))
    end
private
    def output(binary)
        puts binary.words.map { |f| f == "0" ? "□" : "■" }.join.fix_width(6, " ")
    end
end

BinaryClock.new.print

Posted feedbacks - Flatten

Nested Hidden

年月日時分秒 まで表示してみました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
use strict;
use warnings;

# Binary clock

$\="\n";
$,=":";
clear_screen();
while ( 1 )
{
  my ($sec,$min,$hour,$day,$month,$year)=localtime;
  ++$month;
  $year+=1900;
  print bin_($year,'年', 12), sprintf('%4d',$year);
  print bin_($month,'月', 5), sprintf('%4d',$month);
  print bin_($day,'日', 6)  , sprintf('%4d',$day);
  print bin_($hour,'時', 6) , sprintf('%4d',$hour);
  print bin_($min,'分', 7)  , sprintf('%4d',$min);
  print bin_($sec,'秒', 7)  , sprintf('%4d',$sec);
  sleep 1;
  clear_screen();
}

sub bin_
{
  my ($n,$s,$m) = @_;

  '_'x(12-$m) . join '', map { ((1 <<($_-1)) & $n) ? $s : '□' } reverse 1 .. $m;
}

sub clear_screen
{
  if ( $^O =~ /Win32/ ) {
    system('cls');
  }
  else {
    if (system('clear') != 0) {
      print "\x1b[2J";
    }
  }
}

0->o, 1->Oです.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
(use srfi-19)
(define (binary-clock)
  (define (integer->binary-string int)
    (regexp-replace-all
     #/1/
     (regexp-replace-all #/0/ (number->string int 2) "o")
     "O"))
  (let1 cur (time-utc->date (current-time))
        (format #t
                "\n ~2,'0d:~2,'0d\n~6,,,'o@a\n~6,,,'o@a"
                (date-hour cur)
                (date-minute cur)
                (integer->binary-string (date-hour cur))
                (integer->binary-string (date-minute cur)))))
(binary-clock)

1
2
3
4
5
6
7
(use srfi-19)

(print (regexp-replace-all*
        (let1 d (current-date)
          (format " ~5,'0b~%~6,'0b" (ref d 'hour) (ref d 'minute)))
        #/1/ "■"
        #/0/ "□"))

結構素直な方法と思います。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
    class Program
    {
        static void Main(string[] args)
        {
            DateTime now = DateTime.Now;
            byte hours = (byte)now.Hour;
            byte minutes = (byte)now.Minute;
            StringBuilder uh = new StringBuilder();
            StringBuilder lh = new StringBuilder();
            StringBuilder um = new StringBuilder();
            StringBuilder lm = new StringBuilder();
            for (byte i = 0; i < 8; i++)
            {
                byte mask = (byte)(1 << (7 - i));
                if ((hours & mask) != 0)
                {
                    uh.Append("■");
                    lh.Append("□");
                }
                else
                {
                    uh.Append("□");
                    lh.Append("■");
                }
                if ((minutes & mask) != 0)
                {
                    um.Append("■");
                    lm.Append("□");
                }
                else
                {
                    um.Append("□");
                    lm.Append("■");
                }
            }
            Console.Write(uh);
            Console.WriteLine(um);
            Console.Write(lh);
            Console.WriteLine(lm);
            Console.WriteLine(now);
        }

6桁固定、24時、秒まで表示ですが。。。

*Main> :main -- 15:50:14
□□■■■■
■■□□■□
□□■■■□
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import Data.List
import Data.Time
import qualified System.IO.UTF8 as U
import System.Locale

main = getCurrentTime
     >>= utcToLocalZonedTime 
     >>= mapM_ (U.putStrLn . repBin . toBin 6) 
     . read . formatTime defaultTimeLocale "[%H,%M,%S]"

repBin :: [Int] -> String
repBin = map f
  where
    f 1 = '■'
    f 0 = '□'

toBin :: Int -> Int -> [Int]
toBin n m = snd $ mapAccumR divMod m $ replicate n 2

ワンライナー。秒まで表示。0->"o",1->"."です。

1
puts Time.now.to_a[0..2].map{|e| ("%06b"%e).tr("01",".o")}.reverse.join("\n")

0->".",1->"o"の間違いでした。□■で表示なら以下のコード。

1
2
require "jcode"
puts Time.now.to_a[0..2].map{|e| ("%06b"%e).tr("01","□■")}.reverse.join("\n")

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
private import std.stdio, std.date, std.string;

void main() {
    void output(uint n) {
        writeln(format("%06b", n).replace("0", "□").replace("1", "■"));
    }
    
    localTZA = 9 * ticksPerHour; // JST
    auto t = UTCtoLocalTime(getUTCtime());
    output(hourFromTime(t));
    output(minFromTime(t));
    output(secFromTime(t));
}

Squeak Smalltalk で。

1
2
3
4
5
6
7
8
{Time now print24. String streamContents: [:ss |
    (Time now print24 subStrings: ':')
        do: [:each | ss nextPutAll: (
            ((each asInteger radix: 2) forceTo: 7 paddingStartWith: $0)
                translateWith: ({$0 asciiValue + 1 -> $□. $1 asciiValue + 1 -> $■} as: Dictionary))]
        separatedBy: [ss space]]}

"=> #('22:50:58' '□□■□■■□ □■■□□■□ □■■■□■□') "

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#uselib "user32.dll"
#func   PostMessage   "PostMessageA"   int,int,int,sptr
#cfunc  GetWindowLong "GetWindowLongA" int,int
#func   SetWindowLong "SetWindowLongA" int,int,int

#undef  BITNUM
#define global ctype BITNUM(%1) (1 << (%1))

#define WIN_HEIGHT 30
#define CELLSIZE 10
#define CX_MARGIN 1
#define CY_MARGIN 1

    cx = 60 + CX_MARGIN * 2
    cy = WIN_HEIGHT + CY_MARGIN * 2
    bgscr IDW_MAIN, cx, cy, 2
    SetWindowLong hwnd, -20, ( GetWindowLong(hwnd, -20) | 0x80 )
    
    gsel IDW_MAIN, 2
    onclick gosub *OnMove
    onkey   gosub *OnKeyProc
    
    goto *mainlp
    
*mainlp
    gosub *LCalcData
    gosub *LRedraw
    await 10
    goto *mainlp
    
*LCalcData
    nTime = gettime(4), gettime(5), gettime(6)
    return
    
*LRedraw
    redraw 2
    
    color 192, 192, 192 : boxf
    color
    px1 = CX_MARGIN - 1
    py1 = CY_MARGIN - 1
    px2 = ginfo(12) - CX_MARGIN
    py2 = ginfo(13) - CY_MARGIN
    boxf px1, py1, px2, py2
    
    foreach nTime
        h = (192 / length(nTime)) * cnt
        for i, 0, 6
            if ( nTime(cnt) & BITNUM(5 - i) ) {
                s = 255 - ((255 / 10) * i)
                v = 255 - ((255 / 10) * i)
                hsvcolor h, s, v
            } else {
                color 255, 255, 255
            }
            
            px1 = CX_MARGIN + (  i * CELLSIZE)
            py1 = CY_MARGIN + (cnt * CELLSIZE)
            px2 = CX_MARGIN + ((  i + 1) * CELLSIZE) - 2
            py2 = CY_MARGIN + ((cnt + 1) * CELLSIZE) - 2
            boxf px1, py1, px2, py2
        next
    loop
    
    redraw 1
    return
    
*OnMove
    if ( wparam == 1 ) {
        sendmsg hwnd, 0x00A1, 2, 0
    }
    return
    
*OnKeyProc
    if ( iparam == 27 ) {        // [Esc]
        gosub *LQuit
    }
    return
    
*LQuit
    PostMessage hwnd, 0x0010, 0, 0
    return

本体より文字列変換のほうが長くなってしまいました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <string>
#include <limits>
#include <cassert>
#include <ctime>

template<typename T>
std::string tobits(T n, int d)
{
    assert(n > 0);
    assert((0 < d) && (d <= std::numeric_limits<T>::digits));

    std::string result;
    for(T i = static_cast<T>(1) << (d - 1); i > 0; i >>= 1)
    {
        result += ((n & i) != 0) ? "■" : "□";
    }
    return result;
}

int main(int, char* [])
{
    std::time_t raw;
    std::time(&raw);
    std::tm* t = std::localtime(&raw);

    std::cout << tobits(t->tm_hour, 6) << "\n"
              << tobits(t->tm_min,  6) << "\n"
              << tobits(t->tm_sec,  6) << "\n";

    return 0;
}

バッチで。

時分秒を 6桁で表示します。

callを使用するとサブルーチンを呼び出す分だけ時間がかかり、正
確に 1秒を刻めなくなってしまうので、処理をすべて展開しました。

# なお、12行目は 2桁の数値の上位桁が 0である時、 8進数として
# 解釈されないようにするための処理です。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@echo off
setlocal enabledelayedexpansion
  set m=0
  set n=0
  set s=
  set t=
  
  :_
    for /f "delims=." %%t in ("%TIME%") do set t=%%t
    cls
    for %%t in (%t::= %) do (
      set /a n=1%%t-100
      set s=
      for /l %%i in (1,1,6) do (
        set /a m=n%%2
        if !m! equ 0 (set s=□!s!) else (set s=■!s!)
        set /a n/=2
      )
      echo !s!
    )
    ping -n 2 127.0.0.1 > NUL
  goto _
endlocal

強引な1linerで

1
javascript:{String.prototype.pad=function(l,c){var v=this; while(v.length<l){v=c+v;}return v;};d=new Date();alert((d.getHours().toString(2).pad(6,' ')+"\n"+d.getMinutes().toString(2).pad(6,'0')+"\n"+d.getSeconds().toString(2).pad(6,'0')).replace(/0/g,'□').replace(/1/g,'■'))};

しつこく強引な1liner

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
function toBIN { \
  v=$1; \
  s=""; \
  while [ $v -gt 0 ];do \
    let "x = v>>1"; \
    let "b = v ^ x<<1"; \
    s=$b$s; \
    v=$x; \
  done; \
  echo $s; \
}; \
d=`date '+%H %M %S'`; \
c=" "; \
for V in `echo ${d}`;do \
  V=`toBIN $V`; \
  while [ ${#V} -lt 6 ];do \
    V=${c}${V}; \
  done; \
  echo ${V}|sed s/0/□/g|sed s/1/■/g; \
  c="0"; \
done;

もう少し短くしてみました。

 Linuxのprintf(シェルビルトインのものと /usr/bin/printf)では
フラグ文字 0と変換指定子 sを組み合わせても意図した結果が得ら
れなかったので、 dで代用しました。そのため、bcの返す値の最上
位桁が 0にならないことに依存します。

# AIX 4.3.3.0, HP-UX B.11.00, Linux 2.4.2, SunOS 5.5.1で動作
# を確認。
1
for t in `date '+%H %M %S'`; do printf '%06d\n' `echo "obase=2; $t" | bc` | tr '01' '.*'; done

なんのひねりもありません…。

(binary-clock)
■■■■■□■■□□■
■■■
■□□■
■□□□□
■■□□□
■□■□■■
;=> (2009 7 9 16 24 43)
1
2
3
4
5
6
(defun binary-clock (&optional (utime (get-universal-time)))
  (mapc (lambda (x)
          (princ (map 'string (lambda (x) (if (char= #\0 x) #\□ #\■))
                      (format nil "~B" x)))
          (terpri))
        (subseq (nreverse (multiple-value-list (decode-universal-time utime))) 3)))

figureとして表示します。
4:5 を 4:6 にすれば秒も出ます。
MATLABのグレイスケールでは白が1で黒が0ですが、出題の例に合わせて逆にしています。
1を白にするには'0'を'1'にします。
1
2
3
4
function binaryclock
c = clock;
colormap(gray)
imagesc(dec2bin(c(4:5),6)=='0')

LINQを使ってワンライナー的な処理を書いてみました。「Select( binary =>」の部分まで一行にしてしまうと、かえって読みにくくなると判断したのでこの程度で。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(new DateTime(2009, 7, 8, 20, 18, 0));
        Console.WriteLine(BinaryClock.Convert(new DateTime(2009, 7, 8, 20, 18, 0)));
        Console.ReadLine();
    }
}

public class BinaryClock
{
    public static string Convert(DateTime dateTime)
    {
        return string.Join(Environment.NewLine, new int[] { dateTime.Hour, dateTime.Minute }
            .Select(num => System.Convert.ToString(num, 2)).Select(binary =>
            {
                return new string(binary.ToCharArray().Select(c => c == '0' ? '□' : '■').ToArray()).PadLeft(6, ' ');
            }).ToArray());
    }
}


//2009/07/08 20:18:00
// ■□■□□
// ■□□■□

感嘆符はサービスです。

 あたあたあ!
あたたあたた!
  あたたた!
21:36:08
1
2
3
4
5
6
7
$decs = explode(':', date('H:i:s', time()));
foreach ( $decs as $dec ) {
    $search = array('1', '0', ' ');
    $replace = array('あ','た', ' ');
    echo str_replace($search, $replace, sprintf('%6s', decbin($dec)))."!\n";
}
echo implode(':', $decs);

一行野郎。本体73bytes、全部で114bytes。 マルチバイトでなければ-Mスイッチはなくていいです。

1
perl -Mutf8 -Mopen=:utf8 -Mopen=:std -E'say for map { $_ = sprintf "%06b", $_; tr/01/□■/; $_ } (localtime)[2, 1];'

6桁固定、時分秒。
{0,1}を並べることで2進数の列が得られます。
$ echo {0,1}{0,1}
00 01 10 11
あとは配列に入れれば10進→2進変換のできあがり。
1
2
3
4
5
bins=({□,■}{□,■}{□,■}{□,■}{□,■}{□,■})
time=(`date "+%H %M %S"`)
for i in 0 1 2; do
  echo ${bins[time[i]]}
done

ブラウザで表示させると崩れるのが微妙なところ

1
2
3
4
5
<?php
$h = str_replace(array("0","1"),array("□","■"), sprintf(" %05b", date("H")));
$m = str_replace(array("0","1"),array("□","■"), sprintf("%06b", date("i")));
print "$h<br>$m";
?>

なるほど!

Haskellで。

もうちょっとスマートに書けたならなぁ。

0->'.' / 1->'o' です。

1
2
3
4
5
6
7
8
import Data.Time
import System.Locale

digits = [a5:a4:a3:a2:a1:a0:[] | a5<-".o", a4<-".o", a3<-".o", a2<-".o", a1<-".o", a0<-".o"]

main = getCurrentTime
  >>= utcToLocalZonedTime 
  >>= mapM_ (putStrLn.(digits!!)).read.formatTime defaultTimeLocale "[%H,%M,%S]"

スマートかどうかは微妙だけど...

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import Data.Time
import System.Locale
import qualified System.IO.UTF8 as U

bits :: [Char]
bits = "□■"

binReps :: Int -> [[Char]]
binReps 0 = [[]]
binReps n = concatMap (flip map (binReps (n-1)) . (:)) bits

main :: IO ()
main = mapM_ (U.putStrLn . (binReps 6 !!)) 
     . read . formatTime defaultTimeLocale "[%H,%M,%S]" 
     =<< utcToLocalZonedTime =<< getCurrentTime

binRepsの明示的再帰がちょっとスマートでない? それなら、こちらをどうぞ。

1
2
3
4
binReps = (binReps' !!)

binReps' :: [[[Char]]]
binReps' = scanl (concatMap . (.(:)) . flip map) [[]] (repeat bits)

ちょ、おま (^_^;)
1
binReps n = sequence $ replicate n bits

ああますますダサクしてしまった

binReps = sequence . flip replicate bits

でいいんだって。 thanks [1..100]>>=pen


おぉ。勉強になります。ありがとうございます。>[1..100]>>=penさん、nobsunさん。


xbmで出力すればHHMMSSを16進にして流し込むだけで済むはず、との発想から。

xbmでは左から右に描くので、ビット左右反転をすべきなのですが ImageMagickで横着しています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/bin/bash 

date=`date '+%H %M %S'`

echo -e "#define b_width 6\n\
#define b_height 3\n\
static char b_bits[] = {\n\
"`printf '0x%X,' $date`"\n\
};" \
|display -flop -sample 120x240 -

ごくシンプルに。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import java.util.Calendar;
import java.util.GregorianCalendar;

public class BinaryClock {
    public static void main( String[] args ) {
        // 現在時刻を取得する。
        Calendar cal = new GregorianCalendar();

        // 現在時刻から時・分を取得する。
        int hour = cal.get( Calendar.HOUR_OF_DAY );
        int min = cal.get( Calendar.MINUTE );

        // 時・分を二進数に変換する。
        String binHour = Integer.toString( hour, 2 );
        String binMin = Integer.toString( min, 2 );

        // 二進数を表示用文字列に変換する。
        String dispStrHour = binToDispStr( binHour );
        String dispStrMin = binToDispStr( binMin );
        
        // 表示用文字列を出力する。
        System.out.println( dispStrHour );
        System.out.println( dispStrMin );
    }
    
    // 二進数を表示用文字列に変換する。
    private static String binToDispStr( String bin ) {
        String bak = "";
        for ( int i = 0; i < bin.length(); ++i ) {
            if ( bin.charAt( i ) == '0' ) {
                bak += "□";
            } else {
                bak += "■";
            }
        }
        return bak;
    }
}

VBAでもごくシンプルに。

VBAの場合、数値を二進数に変換する関数を実装する必要があった。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
Option Explicit

Public Sub BinaryClock()
    Dim Hour As Integer         '時
    Dim Min As Integer          '分
    Dim BinHour As String       '二進数(時)
    Dim BinMin As String        '二進数(分)
    Dim DispStrHour As String   '表示用文字列(時)
    Dim DispStrMin As String    '表示用文字列(分)

    '// 現在時刻の時・分を取得する。
    Hour = DatePart("h", Now)
    Min = DatePart("n", Now)
    
    '// 時・分を二進数に変換する。
    BinHour = IntToBin(Hour)
    BinMin = IntToBin(Min)
    
    '// 二進数を表示用文字列に変換する。
    DispStrHour = BinToDispStr(BinHour)
    DispStrMin = BinToDispStr(BinMin)
    
    '// 表示用文字列をメッセージボックスに出力する。
    Call MsgBox(DispStrHour & vbNewLine & DispStrMin, _
        vbInformation, _
        "バイナリクロック")
End Sub

'// 数値を二進数に変換する。
Private Function IntToBin(ByVal N As Integer) As String
    Dim Bin As String   '二進数
    
    Bin = ""
    Do While N > 1
        Bin = N Mod 2 & Bin
        N = N \ 2
    Loop
    Bin = N & Bin
    
    IntToBin = Bin
End Function

'// 二進数を表示用文字列に変換する。
Private Function BinToDispStr(ByVal Bin As String) As String
    Dim DispStr As String   '表示用文字列
    Dim i As Integer        'インデックス
    
    DispStr = ""
    For i = 1 To Len(Bin)
        If Mid(Bin, i, 1) = "0" Then
            DispStr = DispStr & "□"
        Else
            DispStr = DispStr & "■"
        End If
    Next
    
    BinToDispStr = DispStr
End Function

先に投稿した#9342を一部変更。

二進数を表示文字列に変換する処理(binToDispStrメソッド)を、文字列置換による実装に変更した。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.util.Calendar;
import java.util.GregorianCalendar;

public class BinaryClock2 {
    public static void main( String[] args ) {
        // 現在時刻を取得する。
        Calendar cal = new GregorianCalendar();

        // 現在時刻から時・分を取得する。
        int hour = cal.get( Calendar.HOUR_OF_DAY );
        int min = cal.get( Calendar.MINUTE );

        // 時・分を二進数に変換する。
        String binHour = Integer.toString( hour, 2 );
        String binMin = Integer.toString( min, 2 );

        // 二進数を表示用文字列に変換する。
        String dispStrHour = binToDispStr( binHour );
        String dispStrMin = binToDispStr( binMin );
        
        // 表示用文字列を出力する。
        System.out.println( dispStrHour );
        System.out.println( dispStrMin );
    }
    
    // 二進数を表示用文字列に変換する。
    // ※文字列置換による実装
    private static String binToDispStr( String bin ) {
        return bin.replaceAll( "0", "□" )
                    .replaceAll( "1", "■" );
    }
}

表示は0と1そのまま。
>jconsole binary_clock.ijs
0 0 0 1 1 1
1 1 0 1 1 1
1
exit echo (6#2) #: 3 4 { 6!:0 ''

Squirrelで。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
function tobits(n, bits)
{
    local ret = "";
    for(local m = 1<<(bits-1); m!=0; m=m>>1) ret += n&m ? "■" : "□";
    return ret;
}
function binclock(d)
{
    print(format(" %s\n", tobits(d.hour, 5)));
    print(format("%s\n", tobits(d.min, 6)));
}

binclock(date());

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
       <meta http-equiv="content-type" content="text/html;charset=utf-8">
       <meta http-equiv="content-script-type" content="text/javascript">
       <meta http-equiv="content-style-type" content="text/css">
       <title>Binary Clock</title>
<style type="text/css">
#clock span{
    display: block;
}
</style>
<script type="text/javascript">
var $ = function(id){ return document.getElementById(id); };

var getBinary = function(num){
    var bNum = '';
    while(num >= 2){
        var mod = num % 2;
        num = (num - mod) / 2;
        bNum = mod + '' + bNum;
    }
    bNum = num + '' + bNum;
    return bNum;
};

var getBinaryClockStr = function(num, length){
    var result = '';
    var bNum = getBinary(num);
    while((bNum + '').length < length){
        bNum = '0' + bNum;
    }
    for(var i=0; i<(bNum+'').length; i++){
        result += bNum.substr(i,1) == '1' ? '■' : '□';
    }
    return result;
};

window.onload = function(){
    var setTime = function(){
        var d = new Date();
        $('hour').innerHTML   = getBinaryClockStr(d.getHours(),5);
        $('minute').innerHTML = getBinaryClockStr(d.getMinutes(),6);
        $('second').innerHTML = getBinaryClockStr(d.getSeconds(),6);
    }
    setInterval(setTime, 1000);
};
</script>
</head>
<body>
<p id="clock"><span id="hour"></span><span id="minute"></span><span id="second"></span></p>
</body>
</html>

少し短くかつPerl 5.8.xでも動くようにしました。-CIOがポイント。

Dan the Perl Monger

1
perl -CIO -Mutf8 -le 'print for map { $_ = sprintf "%06b", $_; tr/01/□■/; $_ } (localtime)[2,1];'

pythonで素直に。timezoneの設定は、サマータイムがない国にとっては面倒なだけです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/python
#coding: utf-8

import datetime

# 横の文字数
cols = 6

# datatimeでJSTを使用する
class tz_jst(datetime.tzinfo):
  def utcoffset(self, dt):
    return datetime.timedelta(hours=9)
  def dst(self, dt):
    return datetime.timedelta()
  def tzname(self):
    return 'JST'

# n: 表示する数字, digits: 表示する桁数, cols: 横の文字数
# one: 1のときに表示する文字, zero: 0のときに表示する文字, padding: paddingに使用する文字
def print_bin(n, digits, cols, one='■', zero='□', padding=' '):
  s = ''
  if cols > digits: s += padding * (cols - digits)

  powers = [2**i for i in range(digits)]
  powers.reverse()
  # オーバーフロー分を切り捨てる
  n = n % 2**digits
  for x in powers:
    s += one if n / x else zero
    n %= x
  print s  

dt = datetime.datetime.now(tz_jst())
print_bin(dt.hour, 5, cols)
print_bin(dt.minute, 6, cols)

お題から少しずれますが、元ネタがウィジェットだそうなので、Java Swing です。
フォントによってしまいますが、見た目が面白いものとして"i/!"にしました。
"Q/O"でも分かりにくくて良いですね。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;

public class SeventeenBarsClock extends JFrame implements ActionListener {
    private static final long serialVersionUID = 1L;
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                SeventeenBarsClock clock = new SeventeenBarsClock();
                clock.pack();
                clock.setLocationRelativeTo(null);
                clock.setVisible(true);
                clock.start();
            }
        });
    }
    private BynaryLabel hourLabel, minuteLabel, secondLabel;
    private javax.swing.Timer timer;
    SeventeenBarsClock() {
        super("17BarsClock");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        hourLabel = new BynaryLabel(5);
        minuteLabel = new BynaryLabel(6);
        secondLabel = new BynaryLabel(6);
        setLayout(new FlowLayout());
        add(hourLabel);
        add(minuteLabel);
        add(secondLabel);
        timer = new javax.swing.Timer(0, this);
        timer.setDelay(1000);
    }
    public void start() { timer.start(); }
    public void stop() { timer.stop(); }
    @Override
    public void actionPerformed(ActionEvent e) {
        Calendar cal = new GregorianCalendar();
        hourLabel.setValue(cal.get(Calendar.HOUR_OF_DAY));
        minuteLabel.setValue(cal.get(Calendar.MINUTE));
        secondLabel.setValue(cal.get(Calendar.SECOND));
    }
    private static class BynaryLabel extends JLabel {
        private static final long serialVersionUID = 1L;
        BynaryLabel(int length) {
            this.length = length;
            setValue(0);
        }
        private int length;
        void setValue(int value) {
            StringBuilder sb = new StringBuilder(length);
            for(int m=1<<(length-1); m>0; m>>=1) sb.append((value & m) != 0 ? "i" : "!");
            setText(sb.toString());
        }
    }
}

誤差が出ないように修正。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
       <meta http-equiv="content-type" content="text/html;charset=utf-8">
       <meta http-equiv="content-script-type" content="text/javascript">
       <meta http-equiv="content-style-type" content="text/css">
       <title>Binary Clock</title>
<style type="text/css">
#clock span{
    display: block;
}
</style>
<script type="text/javascript">
var $ = function(id){ return document.getElementById(id); };

var getBinary = function(num){
    var bNum = '';
    while(num >= 2){
        var mod = num % 2;
        num = (num - mod) / 2;
        bNum = mod + '' + bNum;
    }
    bNum = num + '' + bNum;
    return bNum;
};

var getBinaryClockStr = function(num, length){
    var result = '';
    var bNum = getBinary(num);
    while((bNum + '').length < length){
        bNum = '0' + bNum;
    }
    for(var i=0; i<(bNum+'').length; i++){
        result += bNum.substr(i,1) == '1' ? '■' : '□';
    }
    return result;
};

var fixTime = function(miliSec){
    return miliSec < 501 ? miliSec : -(1000-miliSec);
};

window.onload = function(){
    var g = new Date();
    var setTime = function(){
        var d = new Date();
        g = new Date(g.getTime()+1000);
        $('hour').innerHTML   = getBinaryClockStr(g.getHours(),5);
        $('minute').innerHTML = getBinaryClockStr(g.getMinutes(),6);
        $('second').innerHTML = getBinaryClockStr(g.getSeconds(),6);
        
        setTimeout(setTime, 1000-fixTime(d%1000));
    }
    setTime();
};
</script>
</head>
<body>
<p id="clock"><span id="hour"></span><span id="minute"></span><span id="second"></span></p>
</body>
</html>

秀丸マクロです。
0と1で表示するシンプルなバイナリクロックです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
$bin[0] = "";
$bin[1] = "";
$bin[2] = "";
insert "\n\n\n";

while (1) {
    #i = 0;
    while (#i < 3) {
        call GetBinTime #i;
        if ($bin[#i] != $$return) {
            $bin[#i] = $$return;
            moveto 0,#i;
            beginsel;
            golineend;
            endsel;
            insert $bin[#i];
            gofileend;
        }
        #i = #i+1;
    }
}
endmacro;

GetBinTime:
    refreshdatetime;
    if (##1 == 0) {
        call Dec2Bin val(hour);
    } else if (##1 == 1) {
        call Dec2Bin val(minute);
    } else {
        call Dec2Bin val(second);
    }
    while (strlen($$return) < 6) {
        $$return = " "+$$return;
    }
return $$return;

Dec2Bin:
    $$str = "";
    if (##1!=0) {
    while (##1!=1) {
        $$str = str(##1%2)+$$str;
        ##1 = ##1/2;
    }
    $$str = "1"+$$str;
}
return $$str;

まだなかったので、習作として作ってみました。

また、Wonderflにもあるので良かったら動作するのも見てみてください。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.TimerEvent;
    import flash.geom.ColorTransform;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.utils.Timer;
    
    [SWF(width = 140, height = 80, backgroundColor = 0xCCCCCC, frameRate = 30)]
    
    public class BinaryClock extends Sprite 
    {
        private const UNIT_LENGTH:int = 20;
        
        private var hourPoints:Vector.<Sprite> = new Vector.<Sprite>();
        private var minutePoints:Vector.<Sprite> = new Vector.<Sprite>();
        private var secondPoints:Vector.<Sprite> = new Vector.<Sprite>();
        private var timeTexts:Vector.<TextField> = new Vector.<TextField>();
        
        public function BinaryClock():void
        {
            init();
        }
        
        private function init():void
        {
            (function(points:Vector.<Sprite>):void {
                for (var index:int = 0; index < 5; index++) {
                    var point:Sprite = createPoint();
                    point.x = index * UNIT_LENGTH + UNIT_LENGTH;
                    point.y = 0;
                    points.push(point);
                }
            })(hourPoints);
            var initPoints:Function = function(points:Vector.<Sprite>, y:int):void {
                for (var index:int = 0; index < 6; index++) {
                    var point:Sprite = createPoint();
                    point.x = index * UNIT_LENGTH;
                    point.y = y;
                    points.push(point);
                }
            }
            initPoints(minutePoints, UNIT_LENGTH);
            initPoints(secondPoints, UNIT_LENGTH * 2);
            
            (function(fields:Vector.<TextField>):void {
                for (var index:int = 0; index < 3; index++) {
                    var field:TextField = new TextField();
                    field.width = UNIT_LENGTH;
                    field.height = UNIT_LENGTH;
                    field.x = UNIT_LENGTH * 6;
                    field.y = index * UNIT_LENGTH;
                    field.autoSize = TextFieldAutoSize.CENTER;
                    timeTexts.push(field);
                }
            })(timeTexts);
            
            (function():Vector.<TextField> {
                var result:Vector.<TextField> = new Vector.<TextField>();
                for (var index:int = 0; index < 6; index++) {
                    var field:TextField = new TextField();
                    field.width = UNIT_LENGTH;
                    field.height = UNIT_LENGTH;
                    field.x = UNIT_LENGTH * (5 - index);
                    field.y = 3 * UNIT_LENGTH;
                    field.autoSize = TextFieldAutoSize.CENTER;
                    field.text = String(Math.pow(2, index));
                    result.push(field);
                }
                return result;
            })().map(function(field:TextField, i:int, a:*):void {
                addChild(field);
            });
            
            hourPoints = hourPoints.reverse();
            for each (var hp:Sprite in hourPoints) {
                addChild(hp);
            }
            minutePoints = minutePoints.reverse();
            for each (var mp:Sprite in minutePoints) {
                addChild(mp);
            }
            secondPoints = secondPoints.reverse();
            for each (var sp:Sprite in secondPoints) {
                addChild(sp);
            }
            for each (var field:TextField in timeTexts) {
                addChild(field);
            }
            
            var timer:Timer = new Timer(500);
            timer.addEventListener(TimerEvent.TIMER, setBinaryTime);
            timer.start();
        }

        private function createPoint():Sprite
        {
            var point:Sprite = new Sprite();
            point.graphics.beginFill(0xFFFFFF, 0.6);
            point.graphics.drawRoundRect(0, 0, UNIT_LENGTH, UNIT_LENGTH, UNIT_LENGTH / 2.0, UNIT_LENGTH / 2.0);
            point.graphics.endFill();
            return point;
        }
        
        private function setBinaryTime(event:TimerEvent):void
        {
            var now:Date = new Date();
            
            ([now.hours, now.minutes, now.seconds]).forEach(function(value:int, index:int, a:*):void {
                timeTexts[index].text = ((value < 10)? "0": "") + value;
            });

            var changeColorTime:Function = function(points:Vector.<Sprite>, value:int):void {
                for (var index:int = 0; index < points.length; index++) {
                    var mask:int = (1 << index);
                    changeColor(points[index], (~value & mask) >> index);
                }
            }
            changeColorTime(hourPoints, now.hours);
            changeColorTime(minutePoints, now.minutes);
            changeColorTime(secondPoints, now.seconds);
        }
        
        private function changeColor(s:Sprite, i:Number):void
        {
            s.transform.colorTransform = new ColorTransform(i, i, i, 1, 1, 1, 1, 0);
        }
    }
}

groovyで

1
Calendar.instance.with{n->[HOUR,MINUTE].each{println Integer.toString(n.get(it),2).replaceAll(/./){it=='1'?'■':'□'}}}

パディング処理を忘れてたので追加。 あと「インスタンスごとのメタクラス」使用の方向で。

1
2
3
4
5
'0'.metaClass.getMark = {'□'}
'1'.metaClass.getMark = {'■'}
Calendar.instance.with{now->[HOUR,MINUTE].each{
 println Integer.toString(now.get(it),2).replaceAll(/./){it.intern().mark}.padLeft(6, ' ')}
}

シンプルに、特に目立った点はないです。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include<stdio.h>
#include<time.h>

int main(void)
{
    time_t Time;
    struct tm *t;
    int hour, min, i, 
        hstr[6], mstr[7];

//現在時刻の取得
    
    Time = time(&Time);
    t = localtime(&Time);
    hour = t->tm_hour;
    min = t->tm_min;
    
//2進数に変換して表示
    
    i = 0;
    while(hour)
    {
        hstr[i++] = hour % 2 ? 1 : 0;
        hour /= 2;
    }
    for( ; i < 5; i++)    hstr[i] = 0;
    
    for(i -= 1; i >= 0; i--)
    {
        hstr[i] ? printf("■") : printf("□");
    }
    
    putchar('\n');
    
    i = 0;
    while(min)
    {
        mstr[i++] = min % 2 ? 1 : 0;
        min /= 2;
    }
    for( ; i < 6; i++)    mstr[i] = 0;
    
    for(i -= 1; i >= 0; i--)
    {
        mstr[i] ? printf("■") : printf("□");
    }
    
    return 0;
}

SQL Server 2008 で確認しました。 6 桁固定で、肝心の 2 進数への変換部分は以前投稿した、 http://ja.doukaku.org/comment/9097/ をそのまま使用しました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
DECLARE @now AS datetime = GETDATE(); --'20:18';

WITH
  Input(now_str) AS (
    SELECT LEFT(CONVERT(varchar(max), @now, 8), 5)
  )
, Split(id, n, max_bits) AS (
    SELECT 1, LEFT(now_str, 2), 6 FROM Input
    UNION ALL
    SELECT 2, RIGHT(now_str, 2),6 FROM Input
  )
, ToBin(id, bin, deci, crnt) AS (
    SELECT
        id
      , CAST(CASE
             WHEN n >= POWER(CAST(2 AS bigint), max_bits)
                THEN POWER(CAST(10 AS bigint), max_bits)
                ELSE CAST(0 AS bigint)
             END AS bigint)
      , CASE
        WHEN n >= POWER(CAST(2 AS bigint), max_bits)
           THEN n - POWER(CAST(2 AS bigint), max_bits)
           ELSE n
        END
      , max_bits - 1
    FROM
        Split
    UNION ALL
    SELECT
        id
      , CASE
        WHEN deci >= POWER(CAST(2 AS bigint), crnt)
          THEN POWER(CAST(10 AS bigint), crnt)
          ELSE 0
        END + bin
      , CASE
        WHEN deci >= POWER(CAST(2 AS bigint), crnt)
          THEN deci - POWER(CAST(2 AS bigint), crnt)
          ELSE deci
        END
      , crnt - 1
    FROM
        ToBin
    WHERE
        crnt >= 0
  )
SELECT
    REPLACE(
      REPLACE(
        RIGHT(N'00000' + CAST(bin as nvarchar(6)), 6),
        N'0', N'□'
      ),
      N'1', N'■'
    )
FROM
    ToBin
WHERE
    crnt = -1
ORDER BY
    id

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
let itobin i =
  if i == 0 then [0]
  else
    let rec itob l i = match i with
        0 -> 1::l
      | 1 -> 1::l
      | _ -> itob ((i mod 2)::l) (i/2)
    in itob [] i
;;

let rec padding l = 
  if (List.length l) < 6 then padding (0::l)
  else l
;;

let format_print l = 
  let d = [|"□";"■"|] in 
  let rec square_print l = match l with
    [] -> print_string "\n"
  | s::r -> print_string d.(s);
      square_print r
    in square_print l
;;


let () = 
  let t = Unix.localtime(Unix.time()) in
  format_print (padding (itobin t.Unix.tm_hour));
  format_print (padding (itobin t.Unix.tm_min))
;;

1
javascript:alert(function(t){return t>0?arguments.callee(t/60|0)+'\n'+('00000'+(t%2560).toString(2)).slice(-6).replace(/1/g,'■').replace(/0/g,'□'):''}(((new Date().getTime()/1000|0)+32400)%2586400))

特徴などは特にありませんが、横長にならないようにしてみました。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
object BinClock {
    import java.util._
    def main(args:Array[String]){
        val now = Calendar.getInstance()
        val hour = now.get(Calendar.HOUR_OF_DAY)
        val min = now.get(Calendar.MINUTE)
        val hour_bin = Integer.toBinaryString(hour)
        val min_bin = Integer.toBinaryString(min)
        val hour_shikaku = hour_bin.replace("1","■").replace("0","□")
        val min_shikaku = min_bin.replace("1","■").replace("0","□")
        println(hour_shikaku)
        println(min_shikaku)
    }
}

VBScriptで書いてみました。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Option Explicit

Function formatClock(num, cols)
    Dim strResult, currentNum, i

    strResult = ""
    currentNum = num
    While currentNum > 0
        If currentNum Mod 2 = 0 Then
            strResult = "□" & strResult
        Else
            strResult = "■" & strResult
        End If
        currentNum = Int(currentNum / 2)
    Wend

    For i = 1 To (cols - Len(strResult))
        strResult = "□" & strResult
    Next

    formatClock = strResult
End Function

' 現在日時を取得
Dim currentDate
currentDate = Now()

' バイナリクロック形式にフォーマットして表示
WScript.Echo(formatClock(Hour(currentDate), 5))
WScript.Echo(formatClock(Minute(currentDate), 6))

F#で。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
let strBit order chOn chOff n =
    let rec sub rem res counter =
        if counter = order then
            res
        else
            let ch = if (rem &&& 1) <> 0 then
                        chOn
                     else 
                        chOff
            sub (rem >>> 1) (ch :: res) (counter+1)
    new string( Array.ofList(sub n [] 0))

let tm = System.DateTime.Now
[tm.Hour;tm.Minute]
  |> List.map (strBit 6 '■' '□')
  |> List.iter (fun s -> printfn "%s" s)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using System;
using System.Linq;

namespace ConsoleApplication {
    class Program {
        static void Main(string[] args) {
            // 現在の時刻を表示する
            BinaryClock bc = new BinaryClock();
            Console.WriteLine(bc.ToString());

            // 指定した時刻を表示する
            DateTime dt = new DateTime(2009, 1, 1, 20, 18, 0);
            Console.WriteLine(bc.ToString(dt));
            Console.ReadLine();
        }
    }

    public class BinaryClock {
        private static string ToBinString(int num, int width) {
            string format = string.Format("{{0,{0}}}", width);
            string s = String.Format(format,
                                     System.Convert.ToString(num, 2));
            return s.Aggregate("", (t, c) => t + (c == '1' ? '■' : '□'));
        }

        public string ToString(DateTime dateTime) {
            return " " + ToBinString(dateTime.Hour, 5) + "\n" +
                   ToBinString(dateTime.Minute, 6);
        }

        public override string ToString() {
            return ToString(DateTime.Now);
        }
    }
}

Index

Feed

Other

Link

Pathtraq

loading...