5 февраля 2011 г.

Задача «Треугольник Пифагора»

Ну или оригинальное название (http://habrahabr.ru/blogs/python/111898/) - «Double Squares»
Эта задача из Hacker Cup Qualification Round, очень нравится :
Matraska хочет участвовать в Facebook Hacker Cup 2011 (хоть и заочно) и заодно представить решение этой задачи на ruby ибо python-ом автор опуса не орудует, в отличие от авторов оригинальной статьи (ссылка была в начале абзаца).
Автор (Matraska пр. ред.) позволил себе назвать эту задачу, казалось бы таким уже «истертым» названием, потому что увидел в ней скрытый смысл, о котором будет написано далее. А все скрытое неприменно привлекает внимание и побуждает к действию.
И так текст задачи:
«Найти число представлений целого числа в виде суммы двух полных квадратов целых. Диапазон входящих чисел от нуля до 2147483647.»
Рассмотрим задачу на двух пальцах. Пусть  имеется коллекция целых  неотрицательных чисел m; 0, 2, 67 и т. д. и необходимо определить  для каждого числа количество возможных комбинаций вида
c^2=b^2+a^2,
где с, b и а целые положительные числа.
Почему Пифагора — потому что если обозначить c,  a и b как стороны прямоугольного треугольника, то  c будет гипотенузой, a и b — катетами.
Представляю код:
class Pifagor
  # Метод, который возращает корень входного числа если оно имеет целый корень и nil если иначе
  def simple?(input_number)
    # Dy=number -round(sqrt(number))^2
    dy=input_number- Math.sqrt(input_number).floor**2
    dy==0?Math.sqrt(input_number):nil
  end
  def work(number) #number - то число которое раскладываем
    a_limit=self.simple?(number)
    b_limit=0 # a_limit, b_limit определяют диапазон значений a и b для перебора
    i=0 #кол-во комбинаций
    if !a_limit.nil?
      (0..a_limit).each do|a|
        (0..b_limit).each do |b|
          if(a**2+b**2)==number
            puts("a: #{a}, b: #{b}")
            i+=1
          end
        end
        b_limit+=1# Делаем нижне треугольная матрицу [a_limit x b_limit]
      end
    end
    puts("Number: #{i}")
  end
endSyhi-подсветка кода
Здесь задачу решаем перебором, перебираем в двух циклах от 0 до round(sqrt(c^2) )
Пример вызова:
Pifagor.new.work(25)

25 января 2011 г.

Кирилица в проектах ruby NetBeans

Кратко, суть проблемы:
В проекте Ruby IDE Netbeans  под Windows не отображается кирилица. В то время, как с NetBeans под Убунтой такого небыло - кирилица выводилась без каких-либо проблем.
Решение - необходима настройка проекта ruby:
[окошко "Projects"]=>ПКМ на [названии вашего проекта]=>[Properties]=>[Sources] в открывшемся окне, слева=>[Encoding]выпадающее меню в самом низу=>выбрать интересующую кодировку. Я выбрал Windows-1251.
Перезапуск NetBeans. Все.

13 января 2011 г.

Пример создания пользовательского компонента Битрикс: Корпоративные телефоны.

Введение
Приведем пример создание компонента Битрикса на примере создания компонента «Корпоративные телефоны». Т. е. допустим у нас есть несколько телефонов и в разных разделах необходимо их как-то связано представить общественности (Рис. 1). Причем  имеет смысл выбирать не по одному телефону, а к примеру телефон начальника и его помощника.

Рис. 1
Первым делом расмотрим код вызова компонента и структуру директорий компонента.


<?
$APPLICATION->IncludeComponent("ns_ccom:telefon.bank", ".default", array(
"IBLOCK_ID" => "1",
"SELECTTELEFON" => array(
0 => "KS",
1 => "KP",
),
"SELECT_FIRST" => "Y",
"CACHE_TYPE" => "N",
"CACHE_TIME" => "3600"
),
false
);
?>
Листинг 1.
В листенге 1 в литерной переменной "ns_ccom:telefon.bank" передается необходимая информация для запуска компонента  — пространство имен и  имя компонента Битрикс (формат вызова  - «пространство имен: имя компонента»).
В свою очередь эта запись коррелирована с файловой системой компонента(ов) в Битриксе. Так все компоненты битрикса располагаются в папке /bitrix/components/, а с учетом пространства имен и имени компонента путь до файлов компонента  будет иметь следующий вид:
 /bitrix/components/ ns_ccom/telefon.bank/ (1)
Отсюда следует первый вывод — для того, чтобы создать компонент необходимо воспроизвести путь (1) в файловой системе на хосте.
Литерная переменная ".default" – соответствует о вызове необходимого шаблона компонента. Остальные переменные в массиве array(...) дополнительные параметры компонента Битрикса.
Теперь обратим внимание на файловую структуру компонента относительно пути /bitrix/components/:
[ns_ccom]
[date.current]
[templates]
[.default]
template.php
component.php
.parameters.php
.description.php
Листинг 2 (в квадратных скобках указаны имена директорий)
Замечание: В листинге 2 перечислены основные файлы и папки. Так же в директории date.current могут находится (необязательно):
Директория help -  для хранения файлов файлы помощи по компоненту;
Директория install -  для скриптов инсталляции/деинсталляциии компонента (install.php / uninstall.php);
Директория lang - Нужна для поддержки мультиязычности в компоненте.   
В папке templates размещается шаблон отображаемого компонента. Соответственно в папке .default размещен компонент по умолчанию (см. Листинг 1). 
Пройдемся по файлам
component.php -  Основной исполняемый файл компонента, отвечает за определение состояния модели данных компонента. Проще говоря, наполняет переменную $arResult
.parameters.php - Параметры компонента. Используется для определения параметров комонента (рис. 2). Результат работы переменная $arParams. 
description.php — Описание компонента
template.php — Код шаблонна





Рис. 2
component.php
<?
if(!defined("B_PROLOG_INCLUDED")||B_PROLOG_INCLUDED!==true)die();
if ($this->StartResultCache(3600))
{
$iblock_id = $arParams['ID'];
$arFilter = array('IBLOCK_ID'=>$iblock_id);
//Заполняем содержимым:
$arResult["KS"]="+7(812) 498-36-33";
$arResult["KP"]="+7(812) 325-40-06 доб. 120";
$arResult["CALL"]="+7(812) 325-40-06";
$this->IncludeComponentTemplate();
}
?>
Листинг 2
Вызов метода IncludeComponentTemplate инициализирует и подключает шаблон компонента Битрикса, а  вызов метода die в контексте условного оператора if запрещает вызов файла component.php  независимо от контекста страницы размещения компонента (через адресную строку).
 .parameters.php

<?
if(!defined("B_PROLOG_INCLUDED")||B_PROLOG_INCLUDED!==true)die();
$arComponentParameters = array(
'PARAMETERS' => array(
'IBLOCK_ID' => array(
'NAME' => 'Id инфоблока',
'TYPE' => 'STRING',
'MULTIPLE' => 'N', //Разрешить множественный выбор
'PARENT' => 'BASE',//Раздел настроек
),
'CACHE_TIME' => array('DEFAULT'=>3600),
"SELECTTELEFON" => Array(
"PARENT" => "BASE", //Раздел настроек
"NAME" => "TELPARAM", //Название
"TYPE" => "LIST", //Тип поля
"MULTIPLE" => "Y", //Разрешить множественный выбор
"ADDITIONAL_VALUES" => "N", //Разрешает добавку своих значений к списку
"VALUES" => array(
"KS" => "Кузнецов Сергей", //Пункты для выбора в списке
"KP" => "Кузнецов Павел",
"CALL" => "Официальный телефон банка",
),
"DEFAULT" => "CALL", //Значение по умолчанию
"REFRESH" => "Y", //Отображает кнопку «ОК» для обновления результатов (к примеру при выборе инфоблоков из типов инфоблоков)
),
'SELECT_FIRST' => Array(
'PARENT' => 'BASE',
'NAME' => "Выделять первый номер",
'TYPE' => 'CHECKBOX',
)
)
);
?>

Листинг 3.
В этом файле заполняем хэш таблицу $arComponentParameters которая коррелирует с переменной $arParams, которая доступна для вызова в файлах template.php и component.php.
Ключ 'PARAMETERS' отвечает за наполнение полей на  рис. 1. Как видно для управления доступно 4 опции:
IBLOCK_ID — определяет Id инфоблока (пока в этом компоненте не требуется, но пусть будет ). Тип поля  String;
CACHE_TIME – параметры кэширования;
SELECTTELEFON – Выбор владельца телефона (вообщем чьи телефоны отображать). Тип поля LIST
SELECT_FIRST – параметр для определения выделять ли первый номер телефона из списка. Тип  CHECKBOX.
Пример работы с этими полями будет продемонстрирован, когда дойдем до файла template.php
 .description.php:
В качестве пояснения по этому файлу процитируем из материалов центра разработки (http://dev.1c-bitrix.ru/community/blogs/components2/133.php).
В файле .description.php содержится описание компонента. Это описание применяется для работы с компонентом из среды Битрикс (например, в визуальном редакторе), а так же при работе в режиме редактирования сайта. При работе самого компонента (при обращении к странице, на которой расположен компонент) описание не используется и файл .description.php не подключается.

<?
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die();
$arComponentDescription = array(
"NAME" => 'BankTelefons',
"DESCRIPTION" => 'Список телефонов',
"ICON" => "",
"CACHE_PATH" => "Y",
"PATH" => array(
"ID" => "content", //Главный раздел компонентов, может принимать значения (service, utility, content, communication, e-store)
),
);
?>

Листинг 4
template.php



<style type="text/css">
#telefon_show{
background-color:none;
text-align:center;
}
#telefon_show p.first, #telefon_show p.usual{
font-family: Verdana;
color:#e63500;
}
#telefon_show p.first{
font-size:20px;
font-weight:bold;
padding:2px 0 2px 0;
}
#telefon_show p.usual{
font-size:12px;
font-weight:normal;
}
#telefon_show div.telefon_info{
font-size:15px;
font-weight:bold;
font-family: Verdana;
color:#585858;
}
</style>
<div id="telefon_show">
<div class="telefon_info">Появились вопросы, звоните:</div>

<?
/*Если в $arComponentParameters в качестве типа параметра задавался тип списка ('TYPE'=> 'LIST'),
то получим массив, который можно обработать следующим образом*/
foreach($arParams['SELECTTELEFON'] as $index=>$listParam)
{
//$listParam соответсвует ключу из хэш таблицы VALUES (parameters.php)
$mes="<p";//Сформируем строку которую будем выводить...
if (($arParams['SELECT_FIRST']=='Y')&&($index==0))
$mes.=" class='first'";//Если поставлена метка "Выделить первую строку" и строка первая
else $mes.=" class='usual'";
$mes.=">".$arResult[$listParam]."</p>";
echo $mes;//Печатаем строку
}
?>
<a href="/kontakti/">Как доехать до офиса?</a>
</div>

Листинг 5
В листинге 5 следует обратить внимание на цикл foreach, где происходит обращение к элементу $arParams['SELECTTELEFON'] и $arParams['SELECT_FIRST'] из .parameters.php
В качестве вывода:
Разбиение компонента по решаемым задачам на отдельные файлы до конца не решает  проблему сопровождения кода. Как видно из файлов components.php и template.php в шаблоне не удается вынести логику поведения за рамки представления. Файл components.php не имеет возможности выбора необходимого представления и делегирует эти полномочия пользователю при выборе шаблона компонента.

12 января 2011 г.

puts("there's more than one way to do it. ")

Небольшой пост на тему необходимости использовать плюшек языка(ов) на примере использования унарного амперсанда в Ruby.
Не будем брызгать слюной, сразу перейдем к примерам:
# a) перебираем элементы массива (1..10)
# b) применение лямбда функции ко всем элементам этого массива при помощи &
# Подопытная лямбда
test_lam=lambda{|inPut|
  puts("#{inPut}: #{inPut**2}");
  inPut**2 # В качестве возвращаемого значения
  }
# синтаксис с &
buf=(1..10).to_a.map &test_lam
# классический эквивалент
buf2=(1..10).to_a.map{|input| test_lam.call(input)}

Результат, предсказуем:
1: 1
2: 4
3: 9
4: 16
5: 25
6: 36
7: 49
8: 64
9: 81
10: 100
# Еще один пример
buf2=[1, 2, 3].map(&:to_s)
p buf2 # => ["1", "2", "3"]
# Эквивалент:
p [1, 2, 3].map { |i| i.to_s }
Что лучше? В сети нашел наводящий на мысли бенчмарк на эту тему
# Небольшой Бенчмарк: (http://blog.hasmanythrough.com/2006/3/7/symbol-to-proc-shorthand,
# http://m.onkey.org/let-s-start-with-wtf )
# traditional calls (with a block as in obj.each {|e| e.method_name }) 
# И Унарный амперсаендd to a Proc (like obj.each(&:method_name)).
require 'benchmark'
require 'rubygems'
require 'active_support'
array = [ 1, 'ab', :dog, 3.8 ]
COUNT = 100_000
Benchmark.bmbm(2) do |test|
  test.report('Using Symbol#to_proc') do
    COUNT.times do
      array.map(&:to_s)
    end
  end
  test.report('Standard call') do
    COUNT.times do
      array.map {|e| e.to_s }
    end
  end
end


Полученный результат
=begin
Rehearsal --------------------------------------------------------
Using Symbol#to_proc   1.125000   0.000000   1.125000 (  1.125000)
Standard call                 0.578000   0.000000   0.578000 (  0.578000)
----------------------------------------------------- total: 1.703000sec


                                          user     system      total        real
Using Symbol#to_proc   1.015000   0.000000   1.015000 (  1.015000)
Standard call                0.563000   0.000000   0.563000 (  0.563000)
=end

Может быть показания спидометра и не являются доказательством правильности курса, но примеры с использованием амперсанда проигрывают по времени исполнения «классическому» стилю.

23 декабря 2010 г.

Геттеры и сеттеры в Ruby

Пример работы сеттеров и геттеров в Ruby.
attr_reader  - реализует только геттер для заданного поля
attr_accessor - реализует геттер и сеттер
В примере приведу только на чтение/ запись и чтение (на запись можно сделать по аналогии):
#Пример работы Геттеров и Сеттеров в Ruby
class Setter_and_getter
# Объявляю геттеры и сеттеры
 attr_reader :var_readOnly #Доступ только для чтения
 attr_accessor :var_readWrite #Доступ чтение/записи
 def setData
  @var_readOnly="set" # Устанавливаю значение
  @var_readWrite="r/w";
  puts self.var_readOnly, self.var_readWrite #Проверяю
 end
end
testObj=Setter_and_getter.new
testObj.setData
puts "_________"
#testObj.var_readOnly="fff"; # Получаю ошибку при попытке записи
testObj.var_readWrite="read and write"
puts "I have: #{testObj.var_readOnly}, #{testObj.var_readWrite}" # "Считываю значение"

19 декабря 2010 г.

Добавляем свое меню в Microsoft Bing Maps Silverlight Control

Задача очень проста, создать меню которое будет отображаться на карте.

Меню добавляется в отдельный слой на карте, xaml код:

<m:Map NavigationVisibility="Visible">
  <m:Map.CredentialsProvider>
    <m:ApplicationIdCredentialsProvider ApplicationId="{StaticResource bmk}"/>
  </m:Map.CredentialsProvider>
  <m:Map.Children>
    <m:MapLayer x:Name="ControlLayer"><!-- Собственно меню, вот оно -->
      <Border CornerRadius="5" Width="100" HorizontalAlignment="Right" VerticalAlignment="Top" Background="Black" Opacity="0.8">
        <StackPanel Orientation="Vertical" Margin="5" Height="95">
        <RadioButton Content="Стандарт" GroupName="modeSelection" Foreground="White" IsChecked="True" Name="mode0" Checked="RadioButton_Checked"/>
        <RadioButton Content="Метки" GroupName="modeSelection" Foreground="White" Checked="RadioButton_Checked" Name="mode1"/>
        <RadioButton Content="Редактор" GroupName="modeSelection" Foreground="White" Checked="RadioButton_Checked" Name="mode2"/>
        <RadioButton Content="Навигация" GroupName="modeSelection" Foreground="White" Checked="RadioButton_Checked" Name="mode3"/>
        <StackPanel Orientation="Vertical" x:Name="AnotherControls" Visibility="Collapsed">
          <Button Content="Color" x:Name="colorChange" Click="currentPoint_Click" />
          <Button Content="Delete" x:Name="delComponent" Click="redoLineButton_Click"/>
        </StackPanel>
        <Button Content=">" x:Name="mapMenu"/><!-- Кнопка с помощью которой мы будем "раздвигать" меню -->
        </StackPanel>
      </Border>
    </m:MapLayer>
  </m:Map.Children>
</m:Map>

* This source code was highlighted with Source Code Highlighter.

Код на C#, который может пригодится:

//Обрабатываем расширения меню, которое расположенно в слое на карте
this.mapMenu.Click+=(sen,ev)=>{
  Button currentButton = sen as Button;
  //Если дополнительные пункты меню скрыты => открываем
  if (this.AnotherControls.Visibility == Visibility.Collapsed)
  {
    (currentButton.Parent as Panel).Height += 40;
    this.AnotherControls.Visibility = Visibility.Visible;
    currentButton.Content = "<";
  }
  else//Иначе скрываем
  {
    this.AnotherControls.Visibility = Visibility.Collapsed;
    (currentButton.Parent as Panel).Height -= 40;
    currentButton.Content = ">";
  }
};


* This source code was highlighted with Source Code Highlighter.

27 ноября 2010 г.

WebMatrix. Используем Яндекс в качестве поиска по сайту

Построим поиск по сайту при помощи WebMatrix и поисковика Яндекс. Данную задачу можно было реализовать и на любом языке, но я решил примерить синтаксис Razor к интересной задаче.Суть программки в том, что получив запрос пользователя и его пожелания относительно того что он хочет получить (документ или какой-нибудь материал с сайта), мы делаем запрос к поисковику Yandex. В запросе к серверу мы указываем необходимый сайт и пользовательский запрос. Пользователь получает страницу с поисковой выдачей.
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title></title>
    <link rel="stylesheet" type="text/css" href="main.css"/>
  </head>
  <body>
@using System.Linq;
@using System.Collections.Generic;
        @{
            // У нас есть данные введенные в поле ввода, на основание этого нам нужно сформировать запрос к яндексу
      if(IsPost){
        string text=Request["query"];
        //Проверяем введеную строку, если она не пустая, продолжаем
        if(!String.IsNullOrEmpty(text))
        {
          /*В веденной строке необходимо заменить все пробелы "+"ми.
          Для этих целей используем LINQ */
          IEnumerable<char> textAsChar = text.Select(x=>(x==' ')?'+':x);
          text=new String(textAsChar.ToArray());
          string searchType;метром
          //Определяемся с предпочтениями пользователя, поиск по всему или только по документам
          if (Request["searchtype"]=="all") {searchType="";}
          else {searchType="&mime=pdf&mime=doc&mime=xls";}
          //tetrapolis.ru - сайт на котором производим поиск
          string query=String.Format("http://yandex.ru/yandsearch?date=&text={0}"+
          "&site=tetrapolis.ru&rstr=&zone=all&wordforms=all&lang=ru&mime=all&numdoc=10&lr=2{1}",text,searchType);
          //Делаем переход
          Response.Redirect(query);
        }
      }
    }
  <form method="post" action="">
    <input type="text" name="query" />
    <label for="ContactName"></label>
    <button type="submit">Search</button>
    <br/>
    <input type="radio" name="searchtype" value="all" checked/><label>Общий поиск</label>
    <input type="radio" name="searchtype" value="doc" /><label>По документам</label>
  </form>
  </body>
</html>

main.css:
input[name="query"] {
padding:6px 6px 6px 25px;/* Делаем отступы, самый большой - слева */
font-size: 16px;
color: black;
border: 1px solid #b8b8b8;
/*Делаем круглую рамку (html5) */
-webkit-border-radius:10px;
-moz-border-radius:10px;
/*Добавляем лупу */
background: url('lypa2.jpg') no-repeat;
background-position: left center;
}
button[type="submit"]{
padding:6px;
-moz-border-radius:10px;
-webkit-border-radius:10px;
background-color:#d53e07;
color:white;
font-weight:bold;
}


* This source code was highlighted with Source Code Highlighter.