Page 163 of 173

Arytmetyka modulo + Ruboto + Ruby + Android

W związku z zajęciami z kryptografii, potrzebowałem mieć pod ręką trochę narzędzi umożliwiających obliczenie fi (funkcji Eulera), odwrotności modulo, rozkładu liczby na czynniki pierwsze, wyznaczanie odwrotności modulo macierzy 2x2 oraz mnożenie macierzy 2x2 razy 1x2 oraz obliczenia modulo z duuuuuużych liczb przedstawionych jako potęg. Dlatego też powstał kod działający na Androidzie. Jedyne wymaganie to Ruboto - do znalezienia na Markecie. Jest to JRuby dla Androida, umożliwiający odpalanie prostych skryptów na telefonie. Idealne kiedy trzeba napisać coś na szybko. Zaczniemy od potęgowania. Spróbuj dokonać takiego obliczenia modulo: 12345^12345 mod126 w kalkulatorze na Windows. Chyba się nie udało ;) A ten oto poniższy kod, świetnie sobie z tym radzi:

liczba = 12345
power = 12345
n = 126
#--------------------------------------
def mod(liczba, power, n)
  val = 1

  power.times do |i|
    val *= liczba
    val %= n
  end
  val
end

puts "#{liczba}^#{power}(mod#{n})= #{mod(liczba, power, n)}"

A wynikiem jest: 99 Następnie mamy funkcję Eulera (fi):

liczba = 30
#--------------------------------------
def phi(m)
  r = (2..m)
  primes = r.inject(r){|p, i| p.select{|n| n==i || n%i!=0}}
  primes.inject(m){|e, p| e%p==0 ? e/p*(p-1) : e}
end

puts "fi dla #{liczba} wynosi: #{phi(liczba)}"

Która też działa niczego sobie :) - oczywiście to obliczenie dla zbyt dużych liczb na telefonie komórkowym nie będzie przebiegać zbyt szybko, więc używajcie z rozwagą ;) Kolejnym kawałkiem kodu jest kod obliczający odwrotność zadanej liczby w sensie modulo:

liczba = 315
n = 676
#--------------------------------------

class Integer
  def to_ba(size=128)
    a=[]
    (size-1).downto(0) do |i|
      a<<< 2**index
  }

  val = 1
  powers.each { |pow|
    pow.times do |i|
      val *= liczba
      val %= n
    end
  }
  val
end

def check(liczba, odw, n)
  (liczba*odw)%n == 1
end

odw = odwrotnosc(liczba, n)

if odw == 0
  puts "Odwrotnosc nie istnieje NWD(#{liczba}, #{n}) != 1"
else

  if check(liczba, odw, n)
    puts "#{liczba}^-1 (mod#{n})= #{odw}"
  else
    puts "NWD(#{liczba}, #{n}) != 1"
  end
end

Rozkład liczby na czynniki pierwsze:

liczba = 2

# -----------------------------------------------------------------------------
def factorize(orig)
    factors = {}
    factors.default = 0
    n = orig
    i = 2
    sqi = 4
    while sqi <= n do
        while n.modulo(i) == 0 do
            n /= i
            factors[i] += 1
        end
        sqi += 2 * i + 1
        i += 1
    end

    if (n != 1) && (n != orig)
        factors[n] += 1
    end
    factors
end

def printfactorhash(orig, factorcount)
    print format("%-10d ", orig)
    if factorcount.length == 0
        print "Liczba pierwsza"
    else
        factorcount.sort.each { |factor,exponent|
            print factor
            if exponent > 1
                print "^", exponent
            end
            print " "
        }
    end
    puts
end

n = liczba.to_i
mfactors = factorize(n)
printfactorhash(n, mfactors)

Odwrotność macierzy (w sensie modulo):

MATRIX = [[0,11],
          [17,0]]

#[a, b]
#[c, d]

n = 29

#--------------------------------------

class Integer
  def to_ba(size=128)
    a=[]
    (size-1).downto(0) do |i|
      a<<self[i]
    end
    a
  end
end

def phi(m)
  r = (2..m)
  primes = r.inject(r){|p, i| p.select{|n| n==i || n%i!=0}}
  primes.inject(m){|e, p| e%p==0 ? e/p*(p-1) : e}
end

def odwrotnosc(liczba, n)
  fi = phi(n)

  powers = []
  (fi-1).to_ba.reverse.each_with_index { |b, index|
    next if b == 0
    powers << 2**index
  }

  val = 1
  powers.each { |pow|
    pow.times do |i|
      val *= liczba
      val %= n
    end
  }
  val
end

def nwd(a,b)
  if a > b then a -= b else b -= a end while a != b; return a
end

def det(m)
  m[0][0].to_i*m[1][1].to_i-m[0][1].to_i*m[1][0].to_i
end

def inverse(m, n)

  det = det(m)
  det = det%n

  if nwd(det, n) != 1
    puts "NWD(m, n) != 1"
    exit
  end

  puts "det= #{det}"
  odw_a = odwrotnosc(det, n)
  puts "det^-1mod(#{n})= #{odw_a}"

  w = []
  w << [odw_a*m[1][1]%n, -odw_a*m[0][1]%n ]
  w << [-odw_a*m[1][0]%n, odw_a*m[0][0]%n ]
  w
end

def print_res(w)
  puts "[#{w[0][0]}, #{w[0][1]}]"
  puts "[#{w[1][0]}, #{w[1][1]}]"
end

print_res(inverse(MATRIX, n))

Mnożenie macierzy 2x2 przez 1x2 (w sensie modulo n)

MATRIX1 = [
          [21,19],
          [22,18]]

MATRIX2 = [15, 24]

n = 29

def multiply(m1, m2, n)
  w = [(m1[0][0]*m2[0]+m1[0][1]*m2[1])%n, (m1[1][0]*m2[0]+m1[1][1]*m2[1])%n ]
end

def print_res(res)
  puts "[ #{res[0]}, #{res[1]}]"
end

print_res(multiply(MATRIX1, MATRIX2, n))

Podsumowując: powyżej zamieściłem kod który wykonuje następujące czynności:

  • Obliczanie modulo dużych liczb przedstawionych w postaci potęg
  • Funkcja Eulera - algorytm obliczenia wartości funkcji fi
  • Obliczanie odwrotności liczby w sensie modulo
  • Rozkład liczby na czynniki pierwsze

Mam nadzieję że się przyda :) A tutaj: źródełko

Juggernaut Rails Chat – część VII (emotikonki i dźwięk)

Jeśli dobrnąłeś tutaj i masz działający czat to gratuluję!  W tej, już na pewno ostatniej części zajmiemy się rzeczą może nie aż tak istotną, za to fajną. Dorobimy emotikonki oraz dźwięk nadejścia wiadomości.

Emotikonki

Zacznijmy od emotków. Sprawa wygląda dość prosto. Musimy zastępować tylko emotki tekstowe, takie jak: ":)" wersjami graficznymi czyli po prostu plikami png.

Aby to zrobić napisałem niewielką klasę w libs/:
Klasa emoticoner.rb

class Emoticoner
  ICONS = {
    :smile => {:string => [":)", ";)["], :icon => "smile.png"},
    :happy => {:string => [":D", ";D", ":d", ";d"], :icon => "happy.png"},
    :sad => {:string => [":(", ";("], :icon => "sad.png"},
    :tongue => {:string => [":p", ";p", ":P", ";P"], :icon => "tongue.png"},
  }

  PATH = '/images/emoticons'

  def self.emoticate(msg)
    ICONS.each do |name, row_data|
      row_data[:string].each do |ico|
        msg = msg.gsub(ico, "<img src=\"#{PATH}/#{row_data[:icon]}\" alt=\"\" />")
      end
    end
    msg
  end
end

Jak widzimy, podajemy w stałej ICONS klucz a następnie tablicę "buziek" które mają zostać zastąpione, oraz info na co.
W metodzie statycznej emoticate następuje ta zamiana i zwrócenie już poprawnie wypełnionego ikonkami tekstu.

W stałej PATH przechowujemy informację na temat ścieżki do plików z ikonkami. Teraz wystarczy dodać include w kontrolerze chat:

require ('emoticoner.rb')

I zastąpić przypisanie z parametru do zmiennej msg, następującym kodem:

    msg = Emoticoner.emoticate(h(params[:chat_input]))

Oczywiście do (w moim wypadku) katalogu /images/emoticons wrzucamy pliki z buźkami.

Dźwięk wiadomości

Dorobienie dźwięku wiadomości także nie jest trudne.

Zamieszczamy poniższy kod javascript w kodzie naszej strony:

function DHTMLSound(surl) {
  document.getElementById("dummyspan").innerHTML=
    "<embed src='"+surl+"' hidden=true autostart=true loop=false>";
}

Dodajemy po tagu otwierającym body, taki oto kod html (u nas w layoucie rooms.erb:

<span id=dummyspan></span>

Do akcji send_data dopisujemy jako ostatni element renderu do juggernauta:

      page << "DHTMLSound('/sounds/notice.wav');"

I pamiętamy aby umieścić plik z dzwiękiem w katalogu do którego wskazujemy :)

Mamy juz i emotikonki i dźwięki.

Poniżej zamieszczam kod źródłowy całego projektu. Działa na pewno, ponieważ to na jego bazie robiłem printscreeny :)

Źródełka

Cały zamieszczony tutaj kod możesz dowolnie wykorzystywać w celach edukacyjnych.

Części tutorialu:

  1. Juggernaut Rails Chat – część I (czym jest Juggernaut i jak go zainstalować)
  2. Juggernaut Rails Chat – część II (design)
  3. Juggernaut Rails Chat – część III (rejestracja i logowanie)
  4. Juggernaut Rails Chat – część IV (zarządzanie pokojami)
  5. Juggernaut Rails Chat – część V (łączenie użytkowników z pokojami)
  6. Juggernaut Rails Chat – część VI (odpalamy Juggernaut i nasz chat)
  7. Juggernaut Rails Chat – część VII (emotikonki i dźwięk)

Copyright © 2025 Closer to Code

Theme by Anders NorenUp ↑