C# :: Aufgabe #174 :: Lösung #2

3 Lösungen Lösungen öffentlich
#174

Crowdfunding für Fibonacci-Uhr

Fortgeschrittener - C# von hollst - 24.04.2017 um 12:22 Uhr
Erneut FIBONACCI, jedoch diesmal in einem ganz anderen Zusammenhang.

Im Zuge von Crowdfunding ist in Kanada die sogenannte Fibonacci-Clock (Bild 1)
entwickelt und in die Produktion überführt worden.

(https://www.kickstarter.com/projects/basbrun/fibonacci-clock-an-open-source-clock-for-nerds-wit)

Es sollten für dieses Projekt innerhalb eines Monates (05 - 06/2015) 5.000 CAD
gesammelt werden (ca. 3.500 €), zusammengekommen sind aber sage und schreibe
(über) unglaubliche 125.000 €. Man lernt daraus, dass man mit einer guten (verrückten)
Idee manchmal auch einiges an Geld aquirieren kann.

Dabei ist an der Fibonacci-Clock nichts Kompliziertes dran. Im Grunde besteht sie
lediglich aus einem Display, das in fünf Quadrate mit unterschiedlicher
(variabler) Farbe und (fixer) Kantenlänge aufgeteilt ist.

Die Kantenlängen der Quadrate sind 1, 1, 2, 3 und 5, entsprechen also dem Beginn der
Fibonacci-Sequenz. Es lassen sich damit die Dezimalzahlen 0 ... 12 codieren.

Das Interessante an dem Display ist, dass man damit gleichzeitig
die Stunden und (teilweise) die Minuten darstellen kann. Dies geschieht mittels
wechselnder Farbcodierung der Quadrate und Aufaddition der den Quadraten zugeordnete
Fibonaccizahl. Die Farbe Rot steht für die Stunden, die Farbe Grün für die Minuten.
Wird ein Quadrat sowohl für die Stunden- als auch für die Minutensummation benötigt,
wird dies durch die Farbe Blau angezeigt (Bild 2). Weiß steht für "Nichtnutzung" des
Quadrates. Die Minutenzahl erhält man durch Multiplikation der Minutenzahlsumme mit 5,
somit ist die Genauigkeit der erfindungsgemäßen Uhr auf +- 2.5 Minuten begrenzt,
Vor- und Nachmittagszeiten sind identisch.

Mit den fünf Fibonaccizahlen lassen sich wie gesagt alle Werte von 0 bis 12 darstellen,
d. h. die Minutenanzeige "springt" lediglich alle fünf Minuten. Dies bedeutet allerdings nicht,
dass die Anzeige nicht schneller wechseln darf, denn es gibt mit den Ausnahmen für die
Null und die Zwölf für jede Zahl mehrere Möglichkeiten der Fibonacci-Codierung, die der
kanadische Erfinder auch in kurzen Intervallen und zufällig wechseln läßt.


Die Programmieraufgabe besteht darin, die Fibonacci-Clock mit einer Grafik-Applikation zu
simulieren. Der Minutenwechsel soll allerdings nicht im 5-Minuten-Takt, sondern sogar minütlich
erfolgen. Damit könnte man die Uhr vielleicht als Tester für Schnelldenker einsetzen.

Neben den vier Grundfarben des Erfinders (Weiß, Rot, Grün und Blau (Bild 3))werden also
vier weitere Farben zur Kodierung der fehlenden Additivzahlen 1, 2, 3 und 4 für den Minutenzähler
benötigt. Im Beispiel (Bild 4) sind es die Farben

Yellow (steht für Überlagerung mit Weiß),
Pink (steht für Überlagerung mit Rot),
Purple (steht für Überlagerung mit Grün) und
SkyBlue (steht für Überlagerung mit Blau)

Viel Erfolg!

#2
vote_ok
von hollst (13980 Punkte) - 02.05.2017 um 09:55 Uhr
Quellcode ausblenden C#-Code
using System;
using System.Text;
using System.Windows.Threading;
using System.Windows.Media;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace fibonacci_clock   {

    public partial class MainWindow : Window {
        string LZ = " ";

        bool bo_break = false, bo_break2 = false;
        bool bo_borders_copy_available = false;

        SolidColorBrush[] scb = new SolidColorBrush[]
            { Brushes.AntiqueWhite, Brushes.Red, Brushes.Green, Brushes.Blue,
                    Brushes.Yellow, Brushes.Pink, Brushes.Purple, Brushes.SkyBlue};

        System.Windows.Controls.Border[] borders_copy;

        public MainWindow() {

            InitializeComponent();
            run_dispatcherTimer();
            DispatcherTimer dispatcherTimer = new DispatcherTimer();
            dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
            dispatcherTimer.Interval = new TimeSpan(0, 0, 5);
            dispatcherTimer.Start();
        }

        Random rhm = new Random();

        private void run_dispatcherTimer(bool bo_real = true) {

            DateTime dt = DateTime.Now;

            int h12 = bo_real   ?   dt.Hour % 12    : rhm.Next(12);
            int m5  = bo_real   ?   dt.Minute / 5   : rhm.Next(12);
            int m1  = bo_real   ?   dt.Minute % 5   : rhm.Next(5);

            Fibo fbh = new Fibo(h12);
            Fibo fbm = new Fibo(m5);
            Fibo fbm1 = new Fibo(m1);

            if (bo_break) {                
                MessageBox.Show(dt.ToShortTimeString() + "   " + h12.ToString() +
                    LZ + (m5 * 5).ToString() + LZ + m1.ToString());
                bo_break = false;
            }

            byte[] c = new byte[fbh.fobos.Length];
            for (var i = 0; i < fbh.fobos.Length; i++) 
                c[i] = ((byte)(fbh.fobos[i] + 2 * fbm.fobos[i]));

            byte[] c_extend = new byte[fbh.fobos.Length];
            for (var i = 0; i < fbh.fobos.Length; i++)
                c_extend[i] = ((byte)(fbh.fobos[i] + 2 * fbm.fobos[i] + 4 * fbm1.fobos[i]));

            string titel_string = dt.ToLongTimeString();
            if (bo_break2)
                titel_string = " random simulation ";

          this.main_window.Title = "Fibonacci Clock   " + titel_string +
                LZ + h12.ToString() + LZ + (m5 * 5).ToString() + LZ + m1.ToString() + "    " +
                fbh.fobos.ToMyString() + fbm.fobos.ToMyString() + fbm1.fobos.ToMyString() +
                LZ + c.ToMyString() + c_extend.ToMyString();

            System.Windows.Controls.Border[] borders = new Border[]
                { this.border_1, this.border_2, this.border_3, this.border_4, this.border_5};

            if (!bo_borders_copy_available) {//beim ersten Mal

                borders_copy = new Border[borders.Length];
                for (var i = 0; i < borders_copy.Length; i++)
                    borders_copy[i] = borders[i];

                bo_borders_copy_available = true;
            }

            for (var i = 0; i < fbh.fobos.Length; i++)
                borders[i].Background = scb[c_extend[i]];
        }

        private void dispatcherTimer_Tick(object sender, EventArgs e) { 
            if(!bo_break && !bo_break2) run_dispatcherTimer();
        }

        private void border_1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)                 
            { bo_break = !bo_break; run_dispatcherTimer(); }
        

        private int border_3_state = 0;

        private void border_3_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)        {
            //change window appearance
            border_3_state = (border_3_state + 1) % 2;

            if (border_3_state == 0)    {
                this.main_window.WindowState = WindowState.Normal;
                this.main_window.WindowStyle = WindowStyle.None;
                this.main_window.ResizeMode = ResizeMode.NoResize;
            }
            if (border_3_state == 1)    {//notwendig, um z. B. Uhr ausschalten zu können
                this.main_window.WindowState = WindowState.Normal;
                this.main_window.WindowStyle = WindowStyle.SingleBorderWindow;
                this.main_window.ResizeMode = ResizeMode.CanResize;
            }                       
        }

        int border_1_click_counter = 0;
        private void border_1_MouseDown(object sender, MouseButtonEventArgs e)        {
            //for visual checking the colour appearance
            border_1_click_counter = (border_1_click_counter + 1) % 2;
            int offset = 4;
            if (border_1_click_counter == 1)
                offset = 0;

            if (bo_borders_copy_available)
                for (var i = 0; i < 4; i++)
                    borders_copy[i].Background = scb[i + offset]; 
        }

        private void border_4_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)        {
            //change to simulation
            bo_break2 = !bo_break2;
            this.run_dispatcherTimer(false);
        }
    }

    public class Fibo    {

        static byte[] B5 = new byte[] { 1, 1, 2, 3, 5 };

        public byte[] fobos = new byte[B5.Length];

        Random r = new Random();

        public Fibo(int n)        {

            bool bo_okay = false;
            while(!bo_okay)            {
                int erg = 0;
                for(var i = 0; i < B5.Length; i++)  {
                    byte b = (byte)r.Next(2);
                    fobos[i] = b;
                    erg += b * B5[i];
                }
                bo_okay = erg == n;
            }
        }
    }

    public static class MyExtensions    {

        static public string ToMyString(this byte[] b)        {

            StringBuilder sb = new StringBuilder("[");
            for (var i = 0; i < b.Length; i++)
                sb.Append(b[i].ToString());
            return sb.ToString() + "]";
        }
    }
}


Quellcode ausblenden C#-Code
<Window x:Name="main_window" x:Class="fibonacci_clock.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:fibonacci_clock"
        mc:Ignorable="d"
        Title="fibonacci-clock" Height="300" Width="450" WindowStartupLocation="CenterScreen" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" WindowStyle="None" ResizeMode="NoResize">
    <Grid x:Name="main_grid">
        <Grid.RowDefinitions>
            <RowDefinition Height="50*"/>
            <RowDefinition Height="50*"/>
            <RowDefinition Height="150*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100*"/>
            <ColumnDefinition Width="50*"/>
            <ColumnDefinition Width="250*"/>
        </Grid.ColumnDefinitions>
        <Border x:Name="border_5" BorderBrush="Black" BorderThickness="2,4,4,4" Grid.Column="2" Grid.RowSpan="3" Margin="0" MouseLeftButtonDown="border_1_MouseLeftButtonDown"/>
        <Border x:Name="border_4" BorderBrush="Black" BorderThickness="4,2,2,4" Grid.Row="2" Grid.ColumnSpan="2" MouseLeftButtonDown="border_4_MouseLeftButtonDown" />
        <Border x:Name="border_3" BorderBrush="Black" BorderThickness="4,4,2,2" Grid.RowSpan="2" MouseLeftButtonDown="border_3_MouseLeftButtonDown"/>
        <Border x:Name="border_1" BorderBrush="Black" BorderThickness="2" Grid.Column="1" Grid.Row="1" MouseDown="border_1_MouseDown"/>
        <Border x:Name="border_2" BorderBrush="Black" BorderThickness="2,4,2,2" Grid.Column="1" />
    </Grid>
</Window>

Kommentare:

Für diese Lösung gibt es noch keinen Kommentar

Bitte melden Sie sich an um eine Kommentar zu schreiben.
Kommentar schreiben