ChatGPT не угроза программистам
От: cppguard  
Дата: 28.02.23 23:59
Оценка: 3 (1)
Потрясающе мощная штука, помогает преодолеть информационный шум и в разы повысить продуктивность. По ощущениям получился очень гибкий поисковик по ресурсам в интернете и качество поиска улучшилось настолько же, насколько когда-то улучшилось качество распознавания изображений при переходе от статистических алгоритмов с вручную собранными признаками к свёрточным сетям. К сожалению (или к счастью?) сильным ИИ тут и не пахнет. Я начал с простых энциклопедических вопросов по разным компонентам вроде Docker или systemd, и тут ChatGPT справлялся хорошо. Далее перешёл к логическим задачам и простым программкам на Java. Хоть и с мелкими недочётами, но программа справлялась. Когда же я попросил написать простую программу на Java, которая выводит поле для ввода и подчёркивает текст красное линией, программа выдала текст, явно скопированный откуда-то, который компилировался, но делал совершенно не то, что нужно. Даже после нескольких подсказок, ChatGPT не смог найти проблему, потому что она была связана с взаимодействием компонентов в библиотеке. Далее, я попросил написать алгоритм поиска свободных вершин графа:

Write a program in Java that given a digraph representation in the form of a map of strings to strings, finds the root node.

  в ответ выдался код, который, содержит ненужные действия:
import java.util.*;

public class RootNodeFinder {
    
    public static String findRootNode(Map<String, String> graph) {
        Set<String> allNodes = new HashSet<>(graph.keySet());
    // Вот этот цикл лишний.
        for (String node : graph.values()) {
            allNodes.add(node);
        }
        for (String node : allNodes) {
            if (!graph.containsValue(node)) {
                return node;
            }
        }
        throw new IllegalArgumentException("The graph is not a valid directed acyclic graph.");
    }

    public static void main(String[] args) {
        // Example graph: {"A" -> "B", "B" -> "C", "D" -> "A", "E" -> "C"}
        Map<String, String> graph = new HashMap<>();
        graph.put("A", "B");
        graph.put("B", "C");
        graph.put("D", "A");
        graph.put("E", "C");
        String rootNode = findRootNode(graph);
        System.out.println("The root node is: " + rootNode);
    }
}

Даже после намёка на то, что allNodes.add(node) это лишнее действие, ChatGPT не исправился, а наоборот — стал утверждать, что без этого алгоритм не будет работать корректно:

In this program, the findRootNode method takes a map of strings to strings as input, where the keys represent nodes in the graph and the values represent the nodes they point to. The method first creates a set of all nodes in the graph by adding both the keys and values of the map to a HashSet. It then iterates over each node in the set and checks if it is not present as a value in the map. If a node is not present as a value, then it must be the root node, and the method returns it. If no such node is found, then the graph is not a valid directed acyclic graph, and the method throws an exception.

In the main method, we create an example graph represented as a map, call the findRootNode method on it, and print the result.

Note that this implementation assumes that the input graph is a valid directed acyclic graph (DAG). If the graph contains cycles, then the method will not be able to find the root node, and it may enter an infinite loop or throw an exception. To ensure that the input graph is a DAG, you can add additional checks such as verifying that the graph is acyclic using a topological sort algorithm.

Я подумал, что, возможно, более привычное представление графа это string -> list[string], поэтому предложил переписать алгоритм:

Modify the program so that graph is now represented as a map of strings to list of strings.

  Но в ответ снова получил код, который работает, но содержит лишние действия:
import java.util.*;

public class RootNodeFinder {
    
    public static String findRootNode(Map<String, List<String>> graph) {
        Set<String> allNodes = new HashSet<>(graph.keySet());
    // Снова лишний цикл. Программа взяла код для неориентированного графа?
        for (List<String> adjacentNodes : graph.values()) {
            allNodes.addAll(adjacentNodes);
        }
        for (String node : allNodes) {
            boolean hasIncomingEdges = false;
            for (List<String> adjacentNodes : graph.values()) {
                if (adjacentNodes.contains(node)) {
                    hasIncomingEdges = true;
                    break;
                }
            }
            if (!hasIncomingEdges) {
                return node;
            }
        }
        throw new IllegalArgumentException("The graph is not a valid directed acyclic graph.");
    }

    public static void main(String[] args) {
        // Example graph: {"A" -> ["B"], "B" -> ["C"], "D" -> ["A"], "E" -> ["C"]}
        Map<String, List<String>> graph = new HashMap<>();
        graph.put("A", Arrays.asList("B"));
        graph.put("B", Arrays.asList("C"));
        graph.put("D", Arrays.asList("A"));
        graph.put("E", Arrays.asList("C"));
        String rootNode = findRootNode(graph);
        System.out.println("The root node is: " + rootNode);
    }
}

Только после явного описание того, что я хочу:

I know another solution. Create a list of root node candidates, initializing it with the graph keys. Then for every graph key, remove the corresponding values from the candidate list. After that the candidate list will only contain nodes that has no incoming edges. Can rewrite your code with the following solution in mind?

  программа выдала желаемое решение
import java.util.*;

public class RootNodeFinder {

    public static String findRootNode(Map<String, List<String>> graph) {
        List<String> candidates = new ArrayList<>(graph.keySet()); // initialize candidates with all nodes
        for (List<String> adjacentNodes : graph.values()) {
            candidates.removeAll(adjacentNodes); // remove nodes that have incoming edges
        }
        if (candidates.size() != 1) {
            throw new IllegalArgumentException("The graph is not a valid directed acyclic graph.");
        }
        return candidates.get(0); // return the only remaining node
    }

    public static void main(String[] args) {
        // Example graph: {"A" -> ["B"], "B" -> ["C"], "D" -> ["A"], "E" -> ["C"]}
        Map<String, List<String>> graph = new HashMap<>();
        graph.put("A", Arrays.asList("B"));
        graph.put("B", Arrays.asList("C"));
        graph.put("D", Arrays.asList("A"));
        graph.put("E", Arrays.asList("C"));
        String rootNode = findRootNode(graph);
        System.out.println("The root node is: " + rootNode);
    }
}

Я не привожу весь диалог, потому что он длинный, но там ещё было обсуждение сложности алгоритма, и ChatGPT путался в О-нотации и сложности цикла. Не знаю, как система прошла собеседование в Гугл, если "течёт" на таких простых вопросах. То ли планка в гугле так низко упала, то ли рекламы ради создали новость. Так что мой вердикт — ChatGPT полезный компанион для относительно простых задах, больше связанных с технической частью, особенно, когда нужно быстро разобраться в энциклопедических данных. Сейчас, если вбить подобный вопрос в гугл, приходится продираться сквозь тернии рекламы, всяких форумов и нессмысленных обсуждений на SoF. ChatGPT позволяет за секунды прыгнуть сразу к сути. Система умеет хорошо оперировать различными понятиями, и даже на вопрос с синтаксическими или грамматическими ошибками выдаёт внятный ответ. Можно попросить заменить в коде название переменной, и программа это сделает. Но вот аналитическую часть я бы не доверял — одна и та же беда, что и системами распознавания и вообще любыми AI, построенными на сетях — невозможность осознать, что на входе или на выходе присутствует мусор. Кто работал с AI, тот знает, что это фундаментальная проблема, о которой мало говорят. Так что спим спокойно — работы программистам пока хватит. Хотя, что-то мне подсказывает, что погонщиком джейсонов ChatGPT вполне может устроиться

P.S. Попытался загуглить "java code find root in DAG" и, как и говорил, вся первая страница усеяна ссылками на какие-то бесполезные ресурсы, никакой из которых не содержит тот код, что написала ChatGPT.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.