Prova Final de Linguagens de Programação - DCC024 -



Documentos relacionados
INTRODUÇÃO ÀS LINGUAGENS DE PROGRAMAÇÃO

OBI2014 Caderno de Tarefas

LP II Estrutura de Dados. Introdução e Linguagem C. Prof. José Honorato F. Nunes honorato.nunes@ifbaiano.bonfim.edu.br

Fundamentos de Programação. Turma CI-240-EST. Josiney de Souza.

Orientação a Objetos

OBI2013 Caderno de Tarefas

Introdução às Linguagens de Programação

Componentes da linguagem C++

Java. Marcio de Carvalho Victorino

PROGRAMAÇÃO ESTRUTURADA. CC 2º Período

MC102 Algoritmos e programação de computadores Aula 3: Variáveis

Conceitos básicos da linguagem C

Curso Técnico em Redes

Introdução. Introdução. Introdução. Organização Estruturada de Computadores. Introdução. Máquinas Multiníveis

OBI2007 Caderno de Tarefas

OBI2009 Caderno de Tarefas

Introdução a POO. Introdução a Linguagem C++ e POO

Esta dissertação apresentou duas abordagens para integração entre a linguagem Lua e o Common Language Runtime. O objetivo principal da integração foi

Orientação a Objetos

EXERCÍCIOS SOBRE ORIENTAÇÃO A OBJETOS

Computação L2. Arquivos. Observação: Material da Disciplina Computação Eletrônica CIN/UFPE.

e à Linguagem de Programação Python

Algoritmos e programação

Algoritmos e Estruturas de Dados II. Trabalho Prático 2

ALGORITMOS PARTE 01. Fabricio de Sousa Pinto

JSP - ORIENTADO A OBJETOS

Geração de código intermediário. Novembro 2006

2. OPERADORES ALGORITMOS, FLUXOGRAMAS E PROGRAMAS FUNÇÕES... 10

OBI2014 Caderno de Tarefas

Capítulo 2: Introdução à Linguagem C

Introdução a Java. Hélder Nunes

Programação Orientada a Objetos Prof. Rone Ilídio UFSJ/CAP

Estruturas de Dados. Prof. Gustavo Willam Pereira Créditos: Profa. Juliana Pinheiro Campos

Notas da Aula 4 - Fundamentos de Sistemas Operacionais

Memória Flash. PdP. Autor: Tiago Lone Nível: Básico Criação: 11/12/2005 Última versão: 18/12/2006. Pesquisa e Desenvolvimento de Produtos

Especificação do 3º Trabalho

ARQUITETURA DE COMPUTADORES. Rogério Spindula Rosa

Trabalho 3: Agenda de Tarefas

Diagrama de Classes. Um diagrama de classes descreve a visão estática do sistema em termos de classes e relacionamentos entre as classes.

Prova Final de Linguagens de Programação - DCC024B -

Aula 4 Pseudocódigo Tipos de Dados, Expressões e Variáveis

Programação científica C++

Introdução a Computação

CAPÍTULO 3 - TIPOS DE DADOS E IDENTIFICADORES

PROGRAMAÇÃO ESTRUTURADA. CC 2º Período

Programação de Computadores III

Organização e Arquitetura de Computadores I. de Computadores

3. O NIVEL DA LINGUAGEM DE MONTAGEM

UNIVERSIDADE FEDERAL DO RIO GRANDE DO SUL INSTITUTO DE INFORMÁTICA INFORMÁTICA APLICADA

Orientação a Objetos com Java

Algoritmos e Programação Estruturada

Programação Orientada a Objeto em Python

Análise e Desenvolvimento de Sistemas ADS Programação Orientada a Obejeto POO 3º Semestre AULA 03 - INTRODUÇÃO À PROGRAMAÇÃO ORIENTADA A OBJETO (POO)

Persistência de Dados

Tabela de Símbolos. Análise Semântica A Tabela de Símbolos. Principais Operações. Estrutura da Tabela de Símbolos. Declarações 11/6/2008

Bacharelado em Ciência e Tecnologia Processamento da Informação. Equivalência Portugol Java. Linguagem Java

Curso de Java. Orientação a objetos e a Linguagem JAVA. TodososdireitosreservadosKlais

O que é um algoritmo? O que é um programa? Algoritmos. Programas. Aula 1 Tipo Abstrato de Dados

Lista de Exercícios da 3ª Unidade. ( Ponteiros, Alocação dinâmica, Arquivos, Estruturas de Dados)

Implementando uma Classe e Criando Objetos a partir dela

INF 1005 Programação I

ARRAYS. Um array é um OBJETO que referencia (aponta) mais de um objeto ou armazena mais de um dado primitivo.

Computação II - Java Prof. Adriano Joaquim de Oliveira Cruz Aula Prática - Herança, Polimorfismo e Construtores

Sistemas Operacionais

A lógica de programação ajuda a facilitar o desenvolvimento dos futuros programas que você desenvolverá.

OBI2012 Caderno de Tarefas

Processamento da Informação Teoria. Algoritmos e Tipos de dados

Operaçõe õ s c om o Strings Intr oduç ão a o Ponte iros o e Funçõe õ s

Linguagens de Programação Aula 10

Programação Orientada a Objetos com PHP & MySQL Cookies e Sessões. Prof. MSc. Hugo Souza

AULA 4 VISÃO BÁSICA DE CLASSES EM PHP

ERROS MAIS COMUNS COMETIDOS EM PROGRAMAS E ALGORITMOS

5 - Vetores e Matrizes Linguagem C CAPÍTULO 5 VETORES E MATRIZES

Aula 1 Tipo Abstrato de Dados

Dadas a base e a altura de um triangulo, determinar sua área.

PROJETO LÓGICO DE COMPUTADORES Prof. Ricardo Rodrigues Barcelar

Conceitos de Linguagens de Programação

Introdução à Engenharia de Computação

Construção de Compiladores. Construção de Compiladores. Motivação. Motivação. Contexto Histórico. Classificações: Gerações 09/03/2010

1. NÍVEL CONVENCIONAL DE MÁQUINA

TÉCNICO DE TECNOLOGIA DA INFORMAÇÃO

LINGUAGENS E PARADIGMAS DE PROGRAMAÇÃO. Ciência da Computação IFSC Lages. Prof. Wilson Castello Branco Neto

Aula 2. Objetivos Conceitos; Instalação do Text Pad; Entendendo o código java do AloMundo1 Codificação do AloMundo2,AloMundo3 e AloMundo4.

Algoritmos. Objetivo principal: explicar que a mesma ação pode ser realizada de várias maneiras, e que às vezes umas são melhores que outras.

Introdução à Linguagem

Python: Funções. Claudio Esperança

Conceitos Importantes:

Linguagens de programação

Universidade Federal do Pará Centro de Tecnologia da Informação e Comunicação Grupo de Trabalho SET. Tutorial PyQT4

Resumo da Introdução de Prática de Programação com C. A Linguagem C

Introdução à Programação

Universidade Federal de Rondônia Técnicas de Desenvolvimento de Programas Lista 4

Aula teórica 3. Tema 3.Computadores e linguagens Linguagens de Programação Compilação e linkagem LP Java. Preparado por eng.

Primeira Prova de Linguagens de Programação - DCC024B -

Transcrição:

Prova Final de Linguagens de Programação - DCC024 - Ciência da Computação Nome: Eu dou minha palavra de honra que não trapacearei neste exame. Número de matrícula: As regras do jogo: A prova é sem consulta. Quando terminar, não entregue nada além do caderno de provas para o instrutor. Quando escrever código, a sintaxe correta é importante. Cada estudante tem direito a fazer uma pergunta ao instrutor durante a prova. Traga o caderno de provas quando vier à mesa do instrutor. A prova termina uma hora e quarenta minutos após seu início. Seja honesto e lembre-se: você deu sua palavra de honra. Alguns conselhos: Escreva sempre algo nas questões, a fim de ganhar algum crédito parcial. Se não entender a questão, e já tiver gasto sua pergunta, escreva a sua interpretação da questão junto à resposta. Lembre-se do ganhador do Oscar de melhor filme em 2004. E lembre-se também: perguntando qual foi o filme ganhador você perde a sua pergunta. A prova não é difícil, ela é divertida, então aproveite! Tabela 1: Pontos acumulados (para uso do instrutor) Questão 1 Questão 2 Questão 3 Questão 4 Questão 5 Questão 6 1

1. Existem linguagens em que a indentação é parte da sintaxe. Python é uma destas linguagens. Uma outra linguagem assim foi a primeira versão de Fortran. (a) (2 pontos) Considere, por exemplo, os dois programas abaixo, ambos escritos em Python: def fact1(n): def fact2(n): ans = 1 ans = 1 while n > 1: while n > 1: ans *= n ans *= n n -= 1 n -= 1 return ans return ans O programa da esquerda calcula o fatorial de um inteiro n. O que faz o programa da direita? (b) (4 pontos) Por que Guido van Rossum, o pai de Python, optou por tornar a indentação importante para definir a semântica dos programas? (c) (4 pontos) A indentação também era parte da sintaxe das primeiras versões de Fortran, implementadas no final da década de 50. Porém, naquele caso, a razão desta importância da indentação era bem diferente daquela observada em Python. Por que a indentação era parte da sintaxe das primeiras versões de Fortran? 2

2. Muitas linguagens orientadas à objetos possuem o conceito de classes. Classes permitem que desenvolvedores implementem tipos abstratos de dados. Java e Python são duas linguagens que possuem o conceito de classes. Por exemplo, abaixo temos uma classe Animal implementada em ambas as linguagens: Java class Animal { public void eat() { System.out.println("eating"); public String tostring () { return "Animal"; Python class Animal: def init (self, name): self.name = name def str (self): return "Animal" def eat(self): print "eating." (a) (6 pontos) Embora ambas as linguagens possuam o conceito de classe, elas são implementadas de forma muito diferente nestas linguagens. Preencha a tabela abaixo com um dos seguintes símbolos (nenhuma linguagem), J (Java), P (Python) ou JP (Java e Python), dependendo de cada uma destas linguagens disponibilizar, em sua implementação de classes, a funcionalidade em questão ou não. Funcionalidade Herança múltipla Sobrecarga de métodos nas classes herdeiras Classes como valores de primeira classe Controle de visibilidade Chamada de métodos em tempo O(1) Inserção de novos métodos durante a execução Linguagens que a apresenta (b) (4 pontos) Em geral, tanto Java quanto Python vão usar pesadamente a área de alocação de dados conhecida como heap. Pelo menos estas linguagens tendem a usar o heap mais que C ou Pascal, por exemplo. Por que estas linguagens tendem a usar tanto o heap? 3

3. O programa abaixo, implementado em C, contém duas funções, swap ii e swap dd, que trocam o conteúdo de variáveis inteiras e de ponto flutuante, respectivamente. void swap_ii(int* a, int* b) { int main() { int tmp = *a; int i1 = 2, i2 = 3; *a = *b; double d1 = 2.71, d2 = 3.14; *b = tmp; swap_ii(&i1, &i2); swap_dd(&d1, &d2); void swap_dd(double* a, double* b) { printf("i1=%d, i2=%d\n", i1, i2); int tmp = *a; printf("d1=%lf, d2=%lf\n", d1, d2); *a = *b; *b = tmp; O código deste programa é um tanto quanto redundante: as funções swap ii e swap dd possuem quase o mesmo código, exceto pelo tipo dos parâmetros. Se a linguagem C possuísse alguma forma de polimorfismo paramétrico, então talvez pudéssemos mesclar ambas as funções em uma implementação comum. C não provê este tipo de polimorfismo, porém esta linguagem, que não nos cessa de encantar, possui macros um recurso com o qual podemos aumentar a sua sintaxe. (a) (5 pontos) Implemente uma macro SWAP que receba três coisas: os dois parâmetros que precisam ser trocados, mais o tipo destes parâmetros. SWAP deve ser capaz de implementar tanto a funcionalidade de swap ii quanto swap dd, ou qualquer outra função de troca de variáveis que se pareça com as duas acima. (b) (5 pontos) Re-implemente a função main acima, para que ela utilize duas chamadas à sua macro SWAP em vez das funções swap ii e swap dd. 4

4. (10 pontos) O problema da coloração de grafos é um clássico problema NP-completo: temos um conjunto de cores C, mais um grafo G = (V, E), formado por um conjunto de vértices V e um conjunto de arestas E. O problema pede por uma associação entre elementos de C e vértices em V tal que dados dois vertices v 1 V e v 2 V, se a aresta v 1 v 2 E, então a cor associada a v 1 é diferente da cor associada à v 2. Em Prolog podemos representar este problema como mostrado na figura abaixo: Grafo original: a Uma possível soluçã para o problema da coloração de grafos: bind(a,c2) e b link(a, b). link(b, c). link(c, d). link(d, e). link(e, a). color(c1). color(c2). color(c3). color(c4). color(c5). bind(e,c1) bind(b,c1) d c bind(d,c3) bind(c,c2) sol([bind(a, C1), bind(b, C2), bind(c, C3), bind(d, C4), bind(e, C5)]) :- color(c1), color(c2), color(c3), color(c4), color(c5), \+ invalid([bind(a, C1), bind(b, C2), bind(c, C3), bind(d, C4), bind(e, C5)]). O predicado link(x, Y) é usado para representar as arestas do grafo. Ele é verdade se o vértice X for conectado ao vértice Y. Já o predicado color(c) é verdade se o átomo c for um elemento do conjunto de cores C. O predicado sol(l) é verdade se a lista L for uma solução para o problema da coloração de grafos. Cada elemento desta lista é um átomo composto bind(v, c), que denota o fato de a cor c estar associada ao vértice v. Nesta questão você deve implementar o predicado invalid(l), que é verdade se a lista L não for uma solução válida para o problema da coloração de grafos. Uma solução é invalida se existe uma cor c associada vértices v1 e v2 adjacentes no grafo. Em Prologuês, a solução é invalida se L contém dois elementos bind(v1, c) e bind(v2, c), tal que o predicado link(v1, v2) seja verdadeiro. Não se preocupe com a eficiência de sua implementação. Caso você se lembre dos predicados member e select, então você consegue implementar o predicado invalid com somente duas linhas! Você não precisa implementar member ou select, pois estes predicados fazem parte da biblioteca padrão de Prolog, mas você deve saber a sintaxe correta para usá-los. Se preferir, sinta-se livre para implementar invalid sem usar estes predicados. 5

5. Considere os dois laços abaixo, retirados de um programa escrito em C: (a) for (int k = 0; k < Width * Width; k += Width) { Out[tid] += In[k] / (a - b) - In[k] / (c - d); (b) for (int k = 0; k < Width * Width; k += Width) { Out[tid] += In[k] / (a - b); Out[tid] -= In[k] / (c - d); A tabela abaixo mostra o código assembly que gcc produz para ambos os programas. Primeiro laço (a) $Lt_0_3074: ld.global.f32 %f7, [%r12+0]; mov.f32 %f8, %f6; sub.f32 %f9, %f8, %f5; div.full.f32 %f10, %f7, %f9; sub.f32 %f11, %f4, %f3; div.full.f32 %f12, %f7, %f11; sub.f32 %f13, %f10, %f12; add.f32 %f1, %f1, %f13; st.global.f32 [%r7+0], %f1; setp.lt.u32 %p3, %r12, %r13; @%p3 bra $Lt_0_3074; Segundo laço (b) $Lt_0_3074: mov.f32 %f7, %f6; ld.global.f32 %f8, [%r12+0]; sub.f32 %f9, %f7, %f5; div.full.f32 %f10, %f8, %f9; add.f32 %f11, %f1, %f10; st.global.f32 [%r7+0], %f11; ld.global.f32 %f12, [%r12+0]; sub.f32 %f13, %f4, %f3; div.full.f32 %f14, %f12, %f13; sub.f32 %f1, %f11, %f14; st.global.f32 [%r7+0], %f1; setp.lt.u32 %p3, %r12, %r13; @%p3 bra $Lt_0_3074; Podemos ver que, quando compilando o laço (a), gcc -O3 é capaz de usar somente uma instrução de leitura de memória para obter o valor de In[k], ainda que este valor seja lido duas vezes no interior do laço. Esta instrução é ld.global.f32 %f7, [%r12+0]. Neste caso, gcc -O3 lê o valor armazenado na posição [%r12+0], deposita este valor no registrador %f7, e a partir daí passa a usar somente este registrador, cujo acesso é muito mais rápido que a memória. Infelizmente gcc -O3 não é capaz de otimizar o laço (b). Isto é, mesmo neste nível de otimização, gcc produz duas instruções de carregamento (ld.global.f32) para ler o valor de In[k]. Por que gcc -O3 não pode remover a segunda leitura da memória no caso do laço (b), mantendo o valor lido da primeira vez em um registrador, conforme feito no primeiro laço? 6

6. Uma função recursiva é dita de cauda rasa quando a última coisa que ela faz é chamar-se recursivamente. Re-implemente cada um dos predicados abaixo, para que eles sejam predicados de cauda rasa: (a) (4 Pontos) O predicado que soma os elementos de uma lista: sum([], 0). sum([h T], X) :- sum(t, XAux), X is XAux + H. (b) (4 Pontos) O predicado que inverte os elementos de uma lista: myappend([], L, L). myappend([h T], L, [H LAux]) :- myappend(t, L, LAux). myreverse([], []). myreverse([h T], R) :- myreverse(t, RT), myappend(rt, [H], R). (c) (2 Pontos) Afinal de contas, qual a vantagem de implementarmos funções de cauda rasa? 7