LINUX.ORG.RU

[python]Критика по задачке

 


0

1

Есть простая задачка.

Надо найти количество счастливых билетов (сумма первых 3х цифр равна сумме остальных 3х) для диапазона 000000-999999. А также показать распределение сумм для них.

#!/usr/bin/python
# -*- coding: utf-8 -*- 
i = 0
a = 0
#u = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
#u = range(29)
u = []
while i<1000000:
        na = str (i)
        if i< 10:
		na='0'+na
	if i<100:
		na='0'+na
	if i<1000:
		na='0'+na
	if i<10000:
		na='0'+na
	if i<100000:
		na='0'+na
	q = int(na[0])+int(na[1])+int(na[2])
	w = int(na[3])+int(na[4])+int(na[5])
	if q==w:
		a+=1
		if len(u)<q+1:
			u.append(0)
		u[q]+=1
	i+=1
print "all count="+str( a)
print "sum in luck "
for g in range(len(u)):
	print "Sum is",g,"Exist is",u[g]

Прошу объективной критики.

Pythonic-way :3

print len([(x,y) for x in xrange(1000) for y in xrange(1000) if sum([int(ch) for ch in str(x)]) == sum([int(ch) for ch in str(y)])])

schizoid ★★★
()

Критика:

while i<1000000:
...
i+=1
заменить на
for i in range(1000000):

Вот это:

q = int(na[0])+int(na[1])+int(na[2])
делается так:
q = sum([for ch in str(i % 1000)])
, соответственно для w, в итоге if'ы выше не нужны совершенно.

schizoid ★★★
()

#!/usr/bin/python

заменить на

#!/usr/bin/python2

anonymous
()
print "all count="+str( a)

следует делать так:

print "all count =", a
или так:
print "all count=%d" % a

Список сумм стоит заменить на dict:

u = {}
for ...
    ...
    if q == w:
        a += 1
        if q in u:
            u[q] += 1
        else:[br]
            u[q] = 1

schizoid ★★★
()

Не слушай шизоида. Вот настоящий питоновский код:

#!/usr/bin/env python2
import itertools
import collections

numbers = range(10)

count = 0
sums = collections.defaultdict(int)

for lnums in itertools.product(numbers, numbers, numbers):
    for rnums in itertools.product(numbers, numbers, numbers):
        lsum = sum(lnums)
        if lsum == sum(rnums):
            count += 1
            sums[lsum] += 1

print count
for s in sorted(sums):
    print s, sums[s]
baverman ★★★
()

внезапно

m = [sum(int(j) for j in str(i)) for i in range(0, 1000)]
for i, j in dict((i, m.count(i)) for i in set(m)).items():
	print i, " = ", j * j

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

Тогда уж так:

from itertools import groupby, product
for k, g in groupby(sorted(sum(r) for r in product(*([range(10)] * 3)))):
    sum_count = len(list(g))
    print k, sum_count*sum_count
baverman ★★★
()
Ответ на: комментарий от anonymous

И вообще ужас какой-то, слов нет.

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

спасибо, понравился однострочный вариант. (как я понял, мы выдаем количесво элиментов списка который составлен из всех равенств 2х списков по 1000 элиментов)

с недочетами понял почти все кроме

q = sum([for ch in str(i % 1000)])

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

спасибо, до itertools ещё не дошел но тоже интересно

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

для критики и притащил, ибо хорошая критика дает много пищи для раздумий

ice2heart
() автор топика
Ответ на: комментарий от baverman
-module(lucky).

-compile(export_all).

main() ->
  Nums = lists:seq(0, 9),
  Solve = [[{ticket, [X1,X2,X3,X4,X5,X6]}, {sum, X1+X2+X3}] ||
	    X1 <- Nums,
	    X2 <- Nums,
	    X3 <- Nums,
	    X4 <- Nums,
	    X5 <- Nums,
	    X6 <- Nums, (X1+X2+X3 =:= X4+X5+X6)],
  UniqueSums = lists:usort([Sum || [X,{sum, Sum}] <- Solve]),
  R = lists:map(fun(Sum) ->
		    SumLength = length(lists:filter(
					 fun([_Ticket, {sum, SumSolve}]) ->
					     SumSolve =:= Sum
					 end,
					 Solve)),
		    {Sum, SumLength}
		end,
		UniqueSums),
  io:format("~p ~n", [R]).
adzeitor
()
Ответ на: комментарий от baverman

Что-то вроде этого, только я учусь ещё, так что подозреваю, что это плохое, грязное решение. Была идея сделать с процессами, которые считают, только это для меня ещё сильно геморно.

sum() ->
	N = lists:seq(0, 9),	
	L = [{A, B, C, D, E, F} || A<-N, B<-N, C<-N, D<-N, E<-N, F<-N, A+B+C == D+E+F],
	do_filter_helper(0, L),
	length(L).

do_filter_helper(9*3+1, _L) ->
	ok;

do_filter_helper(N, L) ->
	do_filter(N, 0, L),
	do_filter_helper(N+1, L).

do_filter(N, Sum, []) ->
	io:format("~5w: ~5w~n", [N, Sum]);

do_filter(N, Sum, [H|T]) ->
	{A, B, C, _D, _E, _F} = H,
	if 
		A+B+C == N ->
			do_filter(N, Sum+1, T);
		true ->
			do_filter(N, Sum, T)
	end.
Работает шустро.

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

не, для меня это ещё слишком большое колдунство.

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

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

baverman ★★★
()
Ответ на: комментарий от ice2heart
q = sum([for ch in str(i % 1000)])

Есть число i из [0, 1000000). Находим его младшую часть (i % 1000), переводим в строку (жуткий костыль, наверное, можно проще), и все символы строки (цифры числа, фактически) складываем вместе.

Только, конечно, я забыл привести символ к числу :) Надо так:

q = sum([int(ch) for ch in str(i % 1000)])

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

>а как быть со старшей частью?

Деление нацело вместо модуля.

q = sum([int(ch) for ch in str(i / 1000)])

>и почему if ненужны?

Потому что избыточны. Добавление нуля-символа и последующее приведение его к числу (к нулю же) и суммирование не даёт ровным счётом ничего.

0 + x = x.

sum([int(ch) for ch in "012"]) == sum(int(ch) for ch in "12"])

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

а вот с процессами.

-module(lor).
-export([main/0, counter/1]).

main() ->
	CounterPid = spawn(lor, counter, [dict:new()]),
	N = lists:seq(0, 9),	
	L = [{A, B, C, D, E, F} || A<-N, B<-N, C<-N, D<-N, E<-N, F<-N, A+B+C == D+E+F],
	F = fun(E) ->
		CounterPid ! {add, E}
		end,
	lists:map(F, L),
	CounterPid ! {show_elements, self()},
	receive
		ok ->
			length(L)
	end.
	
counter(Dict) ->
	receive
		{add, E} ->
			{A,B,C,_E,_D,_F} = E,
			counter(dict:update_counter(A+B+C, 1, Dict));
		{show_elements, Pid} ->
			F = fun(K, V) ->
				io:format("~5w: ~10w~n", [K, V])
			end,
			dict:map(F, Dict),
			Pid ! ok
	end.

mi_estas
()

Так чтобы не write only

Из пачки билетов с произвольными номерами выбираем щастливые

#!/usr/bin/env python

def is_happy(N):
    '''
    If ticket has happy number N, return a happy sum.
    '''
    x=[int(c) for c in str(N).zfill(6)]
    s1=sum(x[:3]); s2=sum(x[3:])
    if s1==s2:
        return s1

def happy_tickets(A):
    '''
    Draw all happy numbers from array A and find a distribution of their sums.
    
    Returns:
    nums  - array of happy numbers
    hsums - happy sums
    nrep  - number of repetitions of each sum
    '''
    # Find happy numbers and happy sums first
    nums=[]; sums=[]
    for num in A:
        sum=is_happy(num)
        if isinstance(sum,int):
            nums.append(num); sums.append(sum)

    # Now find a distribution of sums
    hsums=set(sums) # A set of happy sums without repetitions
    nrep=[] # Number of repetitions of each sum
    
    for sum in hsums:
        nrep.append(sums.count(sum))
    return nums,hsums,nrep

# Now test a pack of tickets with odd numbers in range 1:1000000
nums,hsums,nrep=happy_tickets(range(1,1000000,2))

#Print results
print 'Total of ', len(nums), ' happy tickets'
print 'Distribution of sums:'
for i,s in enumerate(hsums):
    print 'Sum= ', s, 'number of repetitions= ', nrep[i]

# If matplotlib is installed, make a plot of distribution
try:
    import matplotlib.pyplot as pl
    pl.figure(1); pl.clf(); pl.bar(hsums,nrep)
    ax=pl.gca(); ax.set_title('Distribution of happy sums')
    ax.set_xlabel('happy sum'); ax.set_ylabel('number of repetitions')
    pl.grid(); pl.show()
except:
    pass

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

На самом деле вместо except: pass правильнее так

except ImportError, err:
    print err

Так при отсутствии matplotlib программа будет нормально завершать работу, а на всех других ошибках сваливаться.

Ещё не забудь, что мой пример учитываетт только нечётные числа. Чтобы решить изначальную задачу, надо в happy_tickets передать всё множество чисел, т.е. range(1000000).

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

угу, я из твоего примера взял только построение графика распределения.

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

угу я понял, первый комент тому подтверждение

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