Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Задача: Города. Покритикуйте. 
:(
    Опции темы
m1st
Дата 19.7.2010, 16:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 73
Регистрация: 1.11.2006

Репутация: нет
Всего: нет



Цитата
Широко известна игра "Города". Называется какой-нибудь город, допустим, "Саратов". Кончается на "в", значит требуется назвать другой город, у которого в названии первая буква "в". Это может быть "Воронеж". Следующий город должен начинаться на "ж" и т.д. Запрещено повторять название городов. Надо написать программу, которая из набора названий городов (все названия разные) строит цепочку максимальной длины.

Привет, решение данной задачи на Java. Покритикуйте. (файл-список городов в аттаче):
Код

package OlympicExercises;

import java.io.*;
import java.util.ArrayList;

public class g6_1011 {
public static void main(String[] args) throws IOException {
BufferedReader in2 = new BufferedReader(new FileReader("src/OlympicExercises/cities.txt"));
String city2;
ArrayList cities = new ArrayList();
while((city2 = in2.readLine()) != null)
cities.add(city2);
in2.close();

String city3, firstChar;
boolean[] used = new boolean[cities.size()];
ArrayList citiesSequenceTMP = new ArrayList(),
citiesSequence = new ArrayList();
for(int i4 = 0; i4 < cities.size(); i4++) {
for(int i3 = 0; i3 < cities.size(); i3++) {
used[i3] = false; }
String city = cities.get(i4).toString();
String lastChar = city.substring(city.length()-1);
for(int i2 = 0; i2 < cities.size(); i2++) {
for(int i = 0; i < cities.size(); i++) {
//                if(cities.get(i).toString().equals(city)) continue;
if(used[i]) continue;
city3 = cities.get(i).toString();
firstChar = city3.substring(0, 1).toLowerCase();
if(firstChar.equals(lastChar)) {
citiesSequenceTMP.add(cities.get(i));
lastChar = city3.substring(city3.length()-1);
used[i] = true;
}
}
if(citiesSequenceTMP.size() > citiesSequence.size()) {
citiesSequence.clear();
citiesSequence.addAll(citiesSequenceTMP);
citiesSequenceTMP.clear();
}
if(citiesSequenceTMP.size() < citiesSequence.size())
citiesSequenceTMP.clear();
}
}
System.out.println(citiesSequence + " = " + citiesSequence.size() + " cities");
}
}


Это сообщение отредактировал(а) m1st - 19.7.2010, 17:49

Присоединённый файл ( Кол-во скачиваний: 14 )
Присоединённый файл  cities.txt 1,73 Kb
PM MAIL   Вверх
Kircul
Дата 19.7.2010, 16:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 166
Регистрация: 20.2.2007

Репутация: 6
Всего: 7



Первое что можно исправить (мое личное мнение) - это при чтении из файла создать коллекцию для поиска такого вида:
Код

Map<Character, Set<String>> citiesIndex = ...; // key - прервая буква города, value - имена городов начинающихся на эту букву

Она поможет исправить поиск города по первой букве.

При использовании какого-нибудь города его просто удалять из коллекции (естественно из копии оригинальной коллекции, созданной при чтении из файла), а не использовать массив used.

Желательно отформатировать исходный код перед отправкой на форум (а то уж очень не удобно читать с такими страшными отступами)

В Java в именах пакетов не принято использовать верхний регистр, а имена классов должно начинаться с большой буквы. 

Данный код:
Код

        String city2;
        ArrayList cities = new ArrayList();
        while((city2 = in2.readLine()) != null)
        cities.add(city2);

по моему лучше смотриться так (но это только мое мнение и к нему не обязательно прислушиваться):
Код
 
        ArrayList cities = new ArrayList();
        for(String city2;(city2 = in2.readLine()) != null;)
                cities.add(city2);


Это сообщение отредактировал(а) Kircul - 19.7.2010, 16:55
PM   Вверх
ivanovpv
Дата 19.7.2010, 17:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Варвар
**


Профиль
Группа: Участник
Сообщений: 639
Регистрация: 26.1.2005
Где: Москва

Репутация: 4
Всего: 28



Алгоритм конечно атас... Так сказать brute-force в самом жестоком виде - так и ребенок напишет. Мне кажется тут надо в первую голову думать над собственно алгоритмом выстраивания самой длинной цепочки, а не о качестве кода - который тоже не ахти. 


--------------------
Aut viam inveniam aut faciam
PM MAIL Skype   Вверх
Kircul
Дата 19.7.2010, 17:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 166
Регистрация: 20.2.2007

Репутация: 6
Всего: 7



"Premature optimization is the root of all evil" ©
ИМХО, не стоит сходу все выкидывать и писать заново, для начала сойдет и составление коллекции citiesIndex, а уж дальше смотреть что еще можно изменить.
PM   Вверх
m1st
Дата 19.7.2010, 18:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 73
Регистрация: 1.11.2006

Репутация: нет
Всего: нет



Цитата(Kircul @  19.7.2010,  16:39 Найти цитируемый пост)
Первое что можно исправить (мое личное мнение) - это при чтении из файла создать коллекцию для поиска такого вида:
Она поможет исправить поиск города по первой букве.
Действительно, отпадает необходимость хранить первую букву в плохочитаемом поле. 
Set<String> сразу решает проблему с дубликатами и ускорением поиска по hashCode().

Цитата(Kircul @  19.7.2010,  16:39 Найти цитируемый пост)
Желательно отформатировать исходный код перед отправкой на форум (а то уж очень не удобно читать с такими страшными отступами)
Сорри, код отформатировал.

Цитата(Kircul @  19.7.2010,  16:39 Найти цитируемый пост)
по моему лучше смотриться так (но это только мое мнение и к нему не обязательно прислушиваться):
По-моему тоже так лучше. Если честно, первый раз увидел такую конструкцию... smile

Спасибо!
PM MAIL   Вверх
ki6opr
Дата 20.7.2010, 08:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 67
Регистрация: 20.12.2006

Репутация: нет
Всего: нет



кстати если заранее неизвестен размер списка, лучше использовать LinkedList, ArrayList основан на массиве и создается с некоторым дефолтным по размеру, когда кол-во элементов превышает размер массива, создается новый и в него копируются значения старого, в LinkedList этого нет.
резюме: 
ArrayList - быстр при доступе по индексу но медленный и неэкономно расходует ресурсы если неизвестно кол-во элементов
LinkedList - быстр при добавлении новых элементов, но медленее при обращении по индексу

+ если вам напрямую ненужны методы ArrayList лучше тип переменной указать как List, работа с интерфейсами или абстрактными классами делает систему более легкой для внесения изминений
мое маленькое имхо smile 

Это сообщение отредактировал(а) ki6opr - 20.7.2010, 09:43
PM MAIL ICQ   Вверх
Kircul
Дата 20.7.2010, 09:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 166
Регистрация: 20.2.2007

Репутация: 6
Всего: 7



Цитата(ki6opr @  20.7.2010,  07:55 Найти цитируемый пост)
+ если вам напрямую ненужны методы ArrayList лучше тип переменной указать как List

Однозначно верно.

[offtopic]
Цитата(ki6opr @  20.7.2010,  07:55 Найти цитируемый пост)
если заранее неизвестен размер списка, лучше использовать LinkedList

А вот это уже спорно, в теории все должно быть так как вы говорите, но на практике ArrayList работает быстрее (при добавлении елементов в конец списка). Сам наткнулся на эти грабли вот тут. LinkedList хорош тогда когда необходимо проводить довольно много добавлений в середину списка.
[/offtopic]
PM   Вверх
jk1
Дата 20.7.2010, 10:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 40
Всего: 75



Цитата

 ArrayList основан на массиве и создается с некоторым дефолтным по размеру, когда кол-во элементов превышает размер массива, создается новый и в него копируются значения старого, в LinkedList этого нет.

Эффект можно минимизировать грамотным заданием capacity при создании листа.
Полностью поддерживаю Kircul, LinkedList предназначен для специфических случаев:
Цитата

If you frequently add elements to the beginning of the List or iterate over the List to delete elements from its interior, you should consider using LinkedList. These operations require constant-time in a LinkedList and linear-time in an ArrayList. But you pay a big price in performance. Positional access requires linear-time in a LinkedList and constant-time in an ArrayList. Furthermore, the constant factor for LinkedList is much worse. If you think you want to use a LinkedList, measure the performance of your application with both LinkedList and ArrayList before making your choice; ArrayList is usually faster.



--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
ivanovpv
Дата 20.7.2010, 14:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Варвар
**


Профиль
Группа: Участник
Сообщений: 639
Регистрация: 26.1.2005
Где: Москва

Репутация: 4
Всего: 28



Если говорить о мелочной оптимизации не самого лучшего алгоритма и кода, то я бы посоветовал:
а) Вместо массива boolean использовать BitSet
б) Вместо String использовать StringBuffer/StringBuilder - это даст существенный выигрыш на текстовых операциях, типа:
Код

                    StringBuffer city = cities.get(i);  //щетаем, что cities содержит StringBuffer'ы - см. далее
                    char firstChar = Character.toLowerCase(city.charAt(0));

в) В циклах убрать постоянное обращение к методу size() - примерно так:
Код

   for (int size4=cities.size(), i4 = 0; i4 < size4; i4++)
        {

        }

г) Вообще постоянное создание стековых переменных в теле цикла - это тоже не очень хорошо - известно что это замедляет скорость
д) Красяво, да и быстрее по скорости можно было бы вместо   ArrayList cities = new ArrayList(); объявить:
Код

  List<StringBuffer> cities = new List<StringBuffer>();

    1) List дешевле ArrayList
    2) Компилятор знает тип объекта внутри списка, так что операция каста будет оптимизирована


--------------------
Aut viam inveniam aut faciam
PM MAIL Skype   Вверх
jk1
Дата 20.7.2010, 14:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 40
Всего: 75



Цитата

 List дешевле ArrayList

ivanovpv
Вы не могли бы пояснить эту мысль? На первый взгляд из преимуществ только loose coupling и возможность подмены реализации. Откуда прирост в скорости?
Я уже не говорю о том, что List - это интерфейс, его инстанс создать никак нельзя. 


--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
powerOn
Дата 20.7.2010, 14:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



Цитата(ivanovpv @  20.7.2010,  15:17 Найти цитируемый пост)
city.charAt(0)

А в чем тут выигрыш?

В классе StringBuffer:
Код

public synchronized char charAt(int index) {
    if ((index < 0) || (index >= count))
        throw new StringIndexOutOfBoundsException(index);
    return value[index];
    }


В классе String:
Код

    public char charAt(int index) {
        if ((index < 0) || (index >= count)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return value[index + offset];
    }


В том, что операция сложения нужна лишняя?



--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
ki6opr
Дата 21.7.2010, 04:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 67
Регистрация: 20.12.2006

Репутация: нет
Всего: нет



Если уж заменять String операции то тогда на StringBuilder, потому как он не thread save, и не будет затрачено время на блокирование. как бы syncronized нехило отъедает ресурсов.

Кстати я насколько знаю компилятор проводит оптимизацию и часто операции с String заменяются на StringBuilder

и плюс много к грамотному заданию Capacity и BitSet. булин в яве сделан через integer если я правильно помню ?

Это сообщение отредактировал(а) ki6opr - 21.7.2010, 04:54
PM MAIL ICQ   Вверх
ivanovpv
Дата 21.7.2010, 09:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Варвар
**


Профиль
Группа: Участник
Сообщений: 639
Регистрация: 26.1.2005
Где: Москва

Репутация: 4
Всего: 28



Цитата(powerOn @  20.7.2010,  15:57 Найти цитируемый пост)
А в чем тут выигрыш?

Не так все однозначно... Я неверно указал на StringBuffer, надо использовать StringBuilder. Прогоните такой тестик:
Код

public static void main(String[] args)
    {
        String s="abrakadabra";
        testString(s);
        testStringBuilder(s);
        testStringBuffer(s);
    }

    public static void testString(String test)
    {
        String s=new String(test);
        char ch;
        long start=System.currentTimeMillis();
        for(int i=0; i < 100000000; i++)
            s.charAt(0);
        long end=System.currentTimeMillis();
        System.out.println("String: "+(end-start)+" - millis");
    }

    public static void testStringBuilder(String test)
    {
        StringBuilder s=new StringBuilder(test);
        char ch;
        long start=System.currentTimeMillis();
        for(int i=0; i < 100000000; i++)
            s.charAt(0);
        long end=System.currentTimeMillis();
        System.out.println("StringBuilder: "+(end-start)+" - millis");
    }

    public static void testStringBuffer(String test)
    {
        StringBuffer s=new StringBuffer(test);
        char ch;
        long start=System.currentTimeMillis();
        for(int i=0; i < 100000000; i++)
            s.charAt(0);
        long end=System.currentTimeMillis();
        System.out.println("StringBuffer: "+(end-start)+" - millis");
    }


На моей системе выдача такая:
Код

String: 281 - millis
StringBuilder: 234 - millis
StringBuffer: 4797 - millis


Так что эффективнее все же StringBuilder

Это сообщение отредактировал(а) ivanovpv - 21.7.2010, 09:08


--------------------
Aut viam inveniam aut faciam
PM MAIL Skype   Вверх
powerOn
Дата 21.7.2010, 10:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



ivanovpv, тест конечно верный. StringBuilder работает быстрее. Вот только 50 мс разница на сто миллиардов операции практически не имеет влияния на производительность. Не такое это уж и узкое место. Разница в реализации метода charAt для классов String и StringBuilder минимальна:

String:
Код

public char charAt(int index) {
        if ((index < 0) || (index >= count)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return value[index + offset];
    }


AbstractStringBuilder:
Код

public char charAt(int index) {
    if ((index < 0) || (index >= count))
        throw new StringIndexOutOfBoundsException(index);
    return value[index];
    }


Выигрыш последнего только за счет отсутствия операции index + offset. На таком огромном количестве операции, что вы проводили при тестировании,  разница может быть и видна. Но на миллионе уже не так.
 


--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
ivanovpv
Дата 21.7.2010, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Варвар
**


Профиль
Группа: Участник
Сообщений: 639
Регистрация: 26.1.2005
Где: Москва

Репутация: 4
Всего: 28



Цитата(powerOn @  21.7.2010,  11:26 Найти цитируемый пост)
Разница в реализации метода charAt для классов String и StringBuilder минимальна:

1) Тут речь идет не столько о методе charAt(), а о других методах. Смысл то в том, что если есть массовые операции над строками - лучше использовать StringBuilder
2) Выигрыш я думаю не в арифметике, а в блокировках

А вообще согласен, все это копейки  smile 



--------------------
Aut viam inveniam aut faciam
PM MAIL Skype   Вверх
Skynin
Дата 21.7.2010, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 359
Регистрация: 1.7.2007
Где: Харьков

Репутация: 6
Всего: 10



Есть еще интересная замена StringBuilder. Для расширения кругозора smile

Представление строк в виде связок символов


PM MAIL WWW ICQ Skype GTalk YIM MSN   Вверх
m1st
Дата 31.8.2010, 17:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 73
Регистрация: 1.11.2006

Репутация: нет
Всего: нет



Следуя вашим советам, вот что получилось:
Код

package olympicexercises;

import java.util.*;
import java.io.*;


public class CitiesSolver
{
  /**
   * Получение первой буквы для сравнения
   *
   * @param city - город для выбора первой буквы
   * @return первая буква
   */
  public static Character getFirstChar(String city)
  {
    return city.charAt(0);
  }


  /**
   * Получение последней буквы для сравнения, с пропуском "неправильных" букв
   *
   * @param city - город для выбора последней буквы
   * @return последняя буква
   */
  public static Character getLastChar(String city)
  {
    int pos = city.length() - 1;
    char lastChar = city.toUpperCase().charAt(pos);
    if (city.toUpperCase().charAt(pos) == 'Й') {
      return 'И';
    }
    else if (lastChar == 'Ь' || lastChar == 'Ы' || lastChar == 'Ъ') {
      pos--;
    }
    return city.toUpperCase().charAt(pos);
  }


  /**
   * Рекурсия обхода дерева
   *
   * @param cities - набор городов для инициализации коллекции
   * @return наиболее длинная цепочка из всех цепочек городов
   */
  public static List<String> findLongestChain(Set<String> cities)
  {
    Map<Character, Set<String>> citiesIndex = createIndex(cities);
    return findLongestChain(citiesIndex);
  }


  /**
   * Рекурсия обхода дерева
   *
   * @param citiesIndex - коллекция городов для поиска
   * @return наиболее длинная цепочка из всех цепочек городов
   */
  private static List<String> findLongestChain(Map<Character, Set<String>> citiesIndex)
  {
    List<String> chain = new ArrayList<String>(0);
    for (Character firstChar : citiesIndex.keySet()) {
      List<String> newChain = findLongestChain(citiesIndex, firstChar);
      System.out.println("Цепочка максимальной длины (" + newChain.size() + "): " + newChain + "\n==");
      if (chain.size() < newChain.size()) {
        chain = newChain;
      }
    }
    System.out.println("Самая длинная из цепочек (" + chain.size() + "): " + chain);
    return chain;
  }


  /**
   * Рекурсия обхода дерева
   *
   * @param citiesIndex - коллекция городов для поиска
   * @param firstChar - первая буква для поиска города
   * @return цепочки городов
   */
  private static List<String> findLongestChain(Map<Character, Set<String>> citiesIndex, Character firstChar)
  {
    List<String> chain = new ArrayList<String>(0);
    try {
      for (String city : citiesIndex.get(firstChar)) {
        Map<Character, Set<String>> index = cloneIndex(citiesIndex); // работаем с копией коллекции городов
        index.get(firstChar).remove(city); // удаляем использованный город
        List<String> newChain = new ArrayList<String>(); // инициализация массива цепочки городов
        newChain.add(city); // добавление города в цепочку
        newChain
            .addAll(findLongestChain(index, getLastChar(city))); // добавление наиболее перспективных городов в цепочку
        System.out.println("Прорабатывается цепочка (" + newChain.size() + "): " + newChain);
        if (chain.size() < newChain.size()) {  // выход из рекурсии
          chain = newChain;
        }
      }
    }
    catch (NullPointerException e) {
    }
    return chain;
  }


  /**
   * Создание копии коллекции городов
   *
   * @param citiesIndex - коллекция городов для копии
   * @return копия коллекции городов
   */
  private static Map<Character, Set<String>> cloneIndex(Map<Character, Set<String>> citiesIndex)
  {
    Map<Character, Set<String>> newIndex = new HashMap<Character, Set<String>>();
    for (Character key : citiesIndex.keySet()) {
      newIndex.put(key, new HashSet<String>(citiesIndex.get(key)));
    }
    return newIndex;
  }


  /**
   * Инициализация коллекции городов для поиска
   *
   * @param cities - города для инициализации
   * @return коллекция городов
   *
   * key - первая буква города, value - имена городов начинающихся на эту букву
   */
  private static Map<Character, Set<String>> createIndex(Set<String> cities)
  {
    Map<Character, Set<String>> index = new HashMap<Character, Set<String>>();
    for (String city : cities) {
      Set<String> cs = index.get(getFirstChar(city));
      if (cs == null) index.put(getFirstChar(city), cs = new HashSet<String>());
      cs.add(city);
    }
    return index;
  }


  public static void main(String[] args) throws IOException
  {
    final Set<String> cities = new HashSet<String>();

    // Загрузим города из файла
    final BufferedReader in = new BufferedReader(new FileReader("src/olympicexercises/cities2.txt"));
    for (String city; (city = in.readLine()) != null;) {
      cities.add(city); // и сложим все имена в этот массив
    }
    in.close();
    Set<String> sortedCities = new TreeSet<String>(cities);
    System.out.println("Список городов (" + sortedCities.size() + "): " + sortedCities);
    System.out.println("----------------------------");

    findLongestChain(cities);
  }
}


Это сообщение отредактировал(а) m1st - 27.9.2010, 13:54
PM MAIL   Вверх
m1st
Дата 27.9.2010, 13:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 73
Регистрация: 1.11.2006

Репутация: нет
Всего: нет



Допустим, существует набор городов "Абв", "Акв", "Вба": для данного набора городов возможны два варианта решения и в моем алгоритме будут вычеслены обе цепочки (хотя это не нужно), как оптимизировать алгоритм так чтобы при таком раскладе вычислялась только одна цепочка (не важно какая)?

Как оптимизировать решения для городов с одинаковыми первой и последней буквой ("Анапа")?
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1196 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.