Let’s assume that your logic or algorithm is quasi-optimal (i.e. mathematically speaking, there is no different procedure or proof to achieve the same result with a substantially smaller number of steps). I mean, your logic conceptual is well defined. So it remains to realize this logic through code - an engineering problem, let’s say - which demands a different kind of strategy. It is in this context, I believe, that your teacher’s statement fits.
A code does not exist in a vacuum. It is inserted in an environment that has its own routines, libraries built-in or external, in addition to code you wrote yourself. All of these are resources that you may or may not use to your advantage when planning a solution.
Reuse of Code
In general, if you can reuse code already ready your solution will be simpler/concise. This is not always true (e.g., if the ready code requires a multitude of parameters and configuration, and you only intend to use a tiny subset of its functionality), but as a rule it will be. And although the complete solution has more code, there is a separation of responsibilities between its logic and each of its dependencies.
Therefore, to achieve a simple logic, the first step is to know your environment well, know what resources are available and whether they apply or not or your case.
Performance
Contrary to common sense, less code does not necessarily mean better performance. Even when external libraries are not involved. A classic example are sorting algorithms, in which the simplest are usually the least efficient. To achieve the best performance it is often necessary to complicate, explore peculiarities of its domain, and abandon the "purity" of its conceptual model in favor of the most appropriate solution to the context.
The question is: is this really necessary? In the vast majority of cases, the answer is nay - you do not need the performance of your program to be the best possible. Citing the example of Daniel Omine, ok, load a 400kb library to save a few characters looks like a bad idea, but is it? First, jQuery code is cleaner, easier to write, and with less problem of incompatibility between browsers. Second, Javascript code is usually small, and is activated in response to a user action, so performance is not critical. Third, with caching you can upload this library once and use at several different points of your system.
That is, if* sacrificing a little performance can have a simpler and concise code, it is good to consider this possibility.
* if and only if - when your code serves as the basis for several other systems (e.g., you are developing a library that can be used for heavy calculations), it is worth sacrificing simplicity in the name of performance.
Abstraction level
Finally, to have a concise code it is necessary to program at the right abstraction level. If you need to read a data structure from a file, do something with it, and save the results in another file, it is not good to mix in the same code different responsibilities (e.g.: open the file and read its bytes; interpret these bytes as language data types; put this data in the structure you will use; use the structure).
Often this means reusing ready-made code, as discussed earlier. In others, it is a matter of breaking down your problem into smaller problems (i.e. "divide to conquer", such as mentioned by Zanoldor), solve each of them and then compose the final solution making use of of individual solutions.
In other words, the total code you write may even be large, but each function or individual module should preferably be concise.
Completion
A good logic need not necessarily have a few lines of code, but an extensive code may be sign that there are problems with your logic (where there is smoke, may have fire). It may be a case of reinventing the wheel, having premature optimization, not being at the right level of abstraction. In another question I gave an answer detailing a little more the matter of the concision of the code. And with the exception that there are many cases in which a good algorithm demands rather extensive code.
+1 for the successful example.
– Jorge B.
Very good example, often this happened to me and went unnoticed. Good tip!
– Rogers Corrêa