I've read a lot of introductory texts to programming, as I have taught programming in a classroom setting to high-school students, and am always on the lookout for better ways to teach it.

(Also, I know quite a few programming languages, both low-level and high-level. I'm a "right tool for the job" sort of person, using different languages on different projects. So I'm not recommending this text out of bias for a certain language.)

My own favorite introductory text for programming, at a high-school level, is https://pine.fm/LearnToProgram, which teaches the Ruby language.

(There's a book version of it linked in the site's sidebar, which might be nice to give as a gift to a prospective student; but the original free online version linked below it — https://pine.fm/LearnToProgram/chap_00.html and onward — is already very good, and is what I usually end up pointing people toward.)

LtP is a very results-oriented tutorial: it just shows you "what" you can do, and gets you going on doing things and experimenting, rather than trying to teach you a lot about "why" things work the way they do. It shows you what works and what doesn't, and uses that to teach-by-example that there are some underlying fundamental principles (e.g. + is addition for Integers and concatenation for Strings, but you can't + a String and an Integer together, because there's no clear meaning when the two things you're +ing don't have the same "type.") It briefly discusses the principle — just enough to know it exists — and then moves on.

I think a results-oriented approach is important at a high-school level, as a learner is at this point still deciding whether they really want to "get into" programming, or if it's "not for them." And I've found that the thing that dissuades teenagers from thinking programming is "for them", usually isn't the struggle of debugging or solving puzzles; rather, it's interminable lessons on theory, that they have no practical foundation yet to motivate a need for understanding of. They need to see results to understand the joys of programming — and to experiment to understand the struggles — but they don't need to be forced through the mind-numbing incomprehension of a CS / Discrete Maths lecture. That can wait until they know enough to ask questions like "why does this program [that has a three-deep hot loop searching a big array by value] run for hours without finishing?" Sell the problem before the solution!

This results-oriented approach is helped by the language choice of Ruby:

• Ruby is a language that has very little boilerplate syntax you must type to make a program work. In a language like Java with much boilerplate, even if a tutorial says "ignore it for now", students itch to know why it's needed. Ruby code just doesn't have anything to cause that itch. Ruby "gets out of the way."

• Ruby has uniform syntax. Most other low-boilerplate languages, a.k.a. scripting languages — I'm specifically thinking of Perl and Python here — have legacy syntax warts that break the learning trance. Ruby's syntax is very predictable, with no real "irregular verbs" to remember. Other languages make students remember — at first with no rule the learner could yet understand — that it's sometimes `len(x)`, but other times it's `x.Len()`. In Ruby, it's always `x.foo`. Even on an integer literal. Even on `nil`!)

These two features of Ruby — no boilerplate, and predictable syntax — also translate to a lot less time being spent helping students debug their syntax instead of their program. (New programmers have a lot of trouble with syntax!)

For a college student who likes math, I might recommend a different text, or even a different language. (I think SICP is pretty great, actually.) But for a young teenager, I think LtP and Ruby are a great place to start.