LINUX.ORG.RU

Наноконкурс по Си :)

 , ,


4

2

Вдохновленный подобным запилю свой маленький топик :) В 2010, читая Седжвика, увидел такую задачу:

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

Проще некуда, ведь правда?

Для ее решения был накрапан такой быдлокод

#include <iostream>
#include <unistd.h>
#include <string.h>

using namespace std;

int main(int argc, char* argv[])
{ const int N = 255;
  const unsigned int sz = 26;
  static int l = 0;
  const char alf[sz]={'a','b','c','d','e','f','g','h','i','j','k','l','m',
						 'n','o','p','q','r','s','t','u','w','x','y','z'};
  int index[sz];
  char str[N];
   for (int i = 0; i < sz;i++)
   {index[i] = 0;
   }
   cin >> str;
   cout <<'\n';
   for ( unsigned int j = 0; j < (strlen(str));j++)
   {   if(str[j] < 0x61)
	   str[j] = _tolower(str[j]);
	 for (int k = 0; k < sz;k++){
		 if (str[j] == alf[k]) index[k]++;}  
   }
    cout <<'\t';
	for(int l = 0; l < sz;l++)
	  if (index[l]) { 
		  cout << alf[l] <<" ";
		  cout << index[l] <<'\n' <<'\t';
	  } 
	sleep(7);
   return 0;
}
Тут правда табуляции корежать линуксовый терминал, немного, но тогда дело было под оффтопом. Из того, что хотелось бы улучшить, например, чтобы программа выводила еще и позицию заданного символа от начала строки.

Короче, принимаются ваши красивые решения господа, а также коменты Царя, про мою тотальную АНскильность, хроническое НИасиляторство и даунизм. You are welcome!

★★★★★

Последнее исправление: beastie (всего исправлений: 3)

Ответ на: комментарий от PolarFox

Не компилируется. Ты просто не забывай обязательные флаги -Wall -Werror. Без них ничего нельзя компилять — мало ли, какую очепятку сделаешь.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от mix_mix

И вот еще в Вашем коде можно от total+1 единичку убрать, принципиально это ничего не поменяет?

Twissel ★★★★★
() автор топика

Ладно, говнокод на пистоне.

import sys

def main():
	chars = {}

	for ch in sys.argv[1]:
		if ch not in chars:
			chars[ch] = 1
		else:
			chars[ch] += 1

	for ch, count in sorted(chars.iteritems(), key=lambda chars: chars[1], reversed=True):
		print ch + ': ' + '*' * count

if __name__ == '__main__':
	main()

z00ke
()

Это не СИ, а плюсплюс. И лучше юзай указатели. Ну а в плюсплюс еще можешь векторы. Это правильнее, чем просто массивы.

ChAnton ★★
()
Ответ на: комментарий от qulinxao

А мне ваше решение понравилось кстати сразу. И компактно, и понятно, и вроде бы ресурсоемко.

И еще beastie ★★★★★ тоже неплох.

Все это учитывая входные условия задачи конечно. Тоесть чистый Си и компактность.

ChAnton ★★
()
Последнее исправление: ChAnton (всего исправлений: 1)
Ответ на: комментарий от qulinxao

Хотя да, наверное без объявления массива дополнительного получиться посложнее. Но все равно можно.

ChAnton ★★
()
Ответ на: комментарий от ChAnton

Объясняю: Книга называется «Фундаментальные алгоритмы на Си++», так что правильно - это Си++.

Раздел назывался «АТД. Строки». На векторах, возможно, получится гибче, но, во-первых, я стремился к минимализму, во-вторых, это книга по алгоритмам, и STL в таких простеньких задачах, ясности не добавит, имхо.

Написал насчет Си специально, т.к. знал, что на сабже можно реализовать задачу красивее и компактнее, что и доказали участники. Если хотите запилите вариант на векторах, во имя Ли и Степанова :)

Twissel ★★★★★
() автор топика
Последнее исправление: Twissel (всего исправлений: 1)
Ответ на: комментарий от Twissel

у седжвика фун алго на С лучше чем на С++

есть ещё на Жабке(но вроде не переводили) у Седжвика.

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

qulinxao ★★☆
()
Ответ на: комментарий от val-amart

Я об этом подумал уже после того как написал.

z00ke
()
Ответ на: комментарий от qulinxao

Спасибо, будет время - гляну. Да, есть на жабке. Но как по мне, она труднее читается, чем крестовая, может потому что английский. А по поводу коэволюции, интересная статья Коли Лихачёва http://l.wzm.me/_nezumi/pdp.htm

Twissel ★★★★★
() автор топика
Ответ на: комментарий от Twissel

Да и хотелось бы услышать мнение авторитетных людей по поводу вышеприведенной истории :)

Twissel ★★★★★
() автор топика

ну куда же вы без меня!

http://emulek.github.io/sed/ch04s05.html

#!/bin/sed -rnf

/^$/ b ctrl_end

G
:begin_loop
		s/^([^\n])([^\n]*)(.*)\n\1~([a-g]+)/\2\n\1~\4a\3/
		t continue_loop
		# символа нет в базе или этот символ последний
		/^\n/	b last_sym

		# новый символ
		s/^(.)([^\n]*)\n$/\2\n\1~a/
		t begin_loop
		s/^(.)(.*)$/\2\n\1~a/
		t begin_loop

:continue_loop
		s/(\n.*)a{10}/\1b/;	T begin_loop
		s/(\n.*)b{10}/\1c/;	T begin_loop
		s/(\n.*)c{10}/\1d/;	T begin_loop
		s/(\n.*)d{10}/\1e/;	T begin_loop
		s/(\n.*)f{10}/\1g/;	T begin_loop
		s/(\n.*)g{10}/\1i/;	T begin_loop
		q 77

	:last_sym
	# последний символ
	s///
	x

:ctrl_end
$ {
	# последняя строка
	s/.*/&/
	t convert_start
:convert_loop
		s/a{9}/9/;		t convert_end_loop
		s/a{8}/8/;		t convert_end_loop
		s/a{7}/7/;		t convert_end_loop
		s/a{6}/6/;		t convert_end_loop
		s/a{5}/5/;		t convert_end_loop
		s/a{4}/4/;		t convert_end_loop
		s/a{3}/3/;		t convert_end_loop
		s/a{2}/2/;		t convert_end_loop
		s/a/1/;			t convert_end_loop
		s/^[a-g]*/&0/;	t convert_end_loop
:convert_end_loop
		y/bcdefg/abcdef/
		s/[a-g]/&/
		t convert_loop
	G
	s/^([0-9]+)\n(.*)([^\n])~[a-g]+(.*)/\2'\3' \1\4/
	x
	t convert_start
	:convert_start
	g
	s/.*[^\n]~([a-g]+).*/\1/
	t convert_loop
	s/\n([^\n]+)\n([^\n]+)\n/\t\1\t\2\n/g
	p
}


а на сишке не интересно.

emulek
()
Ответ на: комментарий от emulek

Рад приветствовать преданного воителя баша. Спасибо за Ваш вклад . Вкурю утром, сейчас спать.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от Twissel

преданного воителя баша.

да я сишнег. Но решать твою задачу на сишке == ходить на медведя с АК-47. А вот с рогатиной типа sed — интересно.

emulek
()
Ответ на: комментарий от emulek

Да и оффтоп просьба глянуть таки на статью К. Касперски по ссылке, действительно ли это был лишь мыльный пузырь. Хотя и хорошо стилистически оформленный. Раз уж Вы сишнег ;) Вот сей пост Наноконкурс по Си :) (комментарий)

Twissel ★★★★★
() автор топика
Последнее исправление: Twissel (всего исправлений: 2)
Ответ на: комментарий от Twissel

Да и оффтоп просьба глянуть таки на статью К. Касперски по (ссылке выше), действительно ли это был лишь мыльный пузырь. Хотя и хорошо стилистически оформленный. Раз уж Вы сишнег ;) Вот сей пост Наноконкурс по Си :) (комментарий)

что я могу сказать? Вполне нормальное поведение. Идём и смотрим таблицу приоритетов операций http://ru.wikipedia.org/wiki/Си_(язык_программирования)#.D0.9F.D1.80.D0.B8.D0...

не сложно заметить, что ++ старше *. Что странного?

emulek
()
Ответ на: комментарий от emulek

Да я вспомнил, что когда первый раз прочитал эту статью, то сразу заглянул в K&R и увидел - все в порядке вещей. А тут такие перлы, но списал на то, что не понял всю глубину проблемы, так сказать. Потому и решил обратится к кому-нибудь еще. Благодарю.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от Twissel

Весьма спорный разбор и объяснение. Надо повнимательнее будет посмотреть. Но представление о том, что:

«Выражение »(*p)[a]++" означает инкремент ячейки «p[0][a]», в то время как «*p[a] += 1» означает инкремент ячейки «p[a][0]»."- являются мягко говоря неочевидными, по нескольким причинам.

Да, вот тут он сам признается, что не знает точно как именно объавлен массив, в качестве одомерного, или многомерного:

" Еще один вопрос — как у Евгения выглядит объявление для «p». Если это массив «T p[N][M]», тогда почему бы не использовать ту же нотацию для доступа к элементам, «p[0][a]++»? А если это указатель на массив «T (*p)[N]», то вид самого объявления уже намекает на использование скобок. Указатель на указатель «T **p» никаких намеков не дает и требует знания приоритетов. "

А потому делать такие далекоидущие выводы в начале своего объяснения, как-то неверно изначально.

ChAnton ★★
()
Последнее исправление: ChAnton (всего исправлений: 1)
Ответ на: комментарий от Twissel

ну то, что в C приоритеты стукнутые, надо просто помнить. Как мы помним правила правописания гласных безударных.

В конце концов, что в этом странного, что ++ старше? А почему — нет? Особенно в C++, где * это обычный оператор, который тоже можно перегружать.

emulek
()
Ответ на: комментарий от ChAnton

«Выражение »(*p)[a]++" означает инкремент ячейки «p[0][a]», в то время как «*p[a] += 1» означает инкремент ячейки «p[a][0]»."- являются мягко говоря неочевидными

это твоя проблема.

emulek
()
Ответ на: комментарий от Twissel

Да, потому что изначально в условии не сказано о том, какого порядка массивы. И если они не многомерные, то разборщик скорее всего не прав)

ChAnton ★★
()
Последнее исправление: ChAnton (всего исправлений: 1)
Ответ на: комментарий от emulek

фигово что () [] . -> ! ~ - ++ — & * (тип) sizeof() разной фиксности

будь они все одностороними определение типа выражения/переменной было бы доступно новичкам.

такое впечатление , что таковой порядок есть издёвка над Аверсоном с его APL

учитывая , что Ритчи был PhD в математике вполне вероятно.

qulinxao ★★☆
()
Ответ на: комментарий от ChAnton

Да, потому что изначально в условии не сказано о том, какого порядка массивы. И если они не многомерные, то разборщик скорее всего не прав)

странный ты... При чём тут вообще массивы? В сишке нет никаких «многомерных массивов», читай K&R.

emulek
()
Ответ на: комментарий от qulinxao

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

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

будь все унарные операции постфиксными ( тогда не приходилось бы определять мозгосгибанием в каком порядке должно парсить достаточно строкового порядка относительно где имя)

приоритеты бы были бы в выражениях где фигурирует несколько аргументов .

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

qulinxao ★★☆
()
Ответ на: комментарий от qulinxao

будь они все одностороними определение типа выражения/переменной было бы доступно новичкам.

Имеется куча ЯП, порог вхождения в которые намного ниже. В которых вообще нет таких ++ и таких *. Подумай, почему все эти ЯП никому нафиг не нужны?

такое впечатление , что таковой порядок есть издёвка над Аверсоном с его APL

это не издёвка, а попытка сделать более удобный синтаксис и семантику, в ущерб математической строгости.

В сишке много таких мест, ещё могу напомнить про целые числа ℤ, которые являются подмножеством натуральных ℕ. (2all, не надо меня посылать в вику, идите на||, я в курсе, что в математике наоборот).

Ну и массивы. В математике есть абстракции «матрица» и т.п., но в компьютере все они обычно представляются в развёрнутом виде, линейной последовательностью чисел. Как и в сишечке. Вместо матрицы 3×3 имеем три массива из трёх чисел записанных вплотную. Т.е. строки и столбцы имеют принципиальное отличие — соседние элементы в строке не соседние.

emulek
()
Ответ на: комментарий от ChAnton

детка, я эту книгу читал лет 20 назад. Никаких «многомерных массивов» в сишке нет, не было, и не будет. Есть массивы состоящие из массивов, да и то, только внутри одной функции.

emulek
()
Ответ на: комментарий от emulek

Все понятно) Дальше разговор с тобой не имеет никакого смысла.

http://citforum.ru/programming/c/h17.shtml

http://www.c-cpp.ru/books/mnogomernye-massivy

Далее, открываем упомянутый тобой Керниган-Ричи:

http://lanzog.narod.ru/liter/kernigan-c/kernigan-c.html#5-7

Все есть, как и говорил.

Учись студент.

ChAnton ★★
()
Последнее исправление: ChAnton (всего исправлений: 2)
Ответ на: комментарий от emulek

Дай определение многомерного массива. Что-то у меня после С понятие "многомерный массив" четко ассоциируется с массивом массивов.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от emulek

по авторитетному(гугль в руки) мнению Ритчи

1. тюнил рабочий инструмент.

2. Он же (Ритчи) весьма был слаб в трансляции поэтому куча С-конструкций в Сях парсилось изначально не топдаун парсером , а что то наподобии строкового парсера , ошмётки этого остались даже в вызове for и if функций

3. про множества значений ( а тип это не множество , а множество и набор операций на них) там пересечение , а не включение ( в случае сигнед ансигнед)

qulinxao ★★☆
()
Ответ на: комментарий от qulinxao

Это объяснение меня удовлетворило. Остальных, думаю, тоже.

Twissel ★★★★★
() автор топика
Ответ на: комментарий от Eddy_Em

Дай определение многомерного массива. Что-то у меня после С понятие «многомерный массив» четко ассоциируется с массивом массивов.

в двухмерном массиве строки эквивалентны столбцам, и индексы тоже взаимозаменяемы. Т.е. транспонирование матрицы не занимает времени и тривиально.

А массив массивов это общепринятая эмуляция многомерного массива. Но в C она встроена в семантику ЯП.

emulek
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.